Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x7004h: No llamés exit() en funciones de biblioteca: propagá el error

Robustez y manejo de errores (0x70XX)

Universidad Nacional de Río Negro

0x7004h: No llamés exit() en funciones de biblioteca: propagá el error

Enunciado normativo

Las funciones de biblioteca o de módulo NO DEBEN terminar el proceso con exit() ni abort() ante un error. DEBEN informar el fallo mediante su valor de retorno (o un parámetro de salida) y dejar que el llamador decida cómo reaccionar. Sólo main (o una función de nivel de aplicación documentada) puede terminar el proceso.

¿Por qué existe esta regla?

El problema

Una función de biblioteca que llama a exit() le quita el control al llamador. Ese llamador podría haber querido reintentar, informar el error, liberar recursos o seguir procesando otros datos; en cambio, el proceso muere sin posibilidad de respuesta.

Además, exit() cierra el programa sin devolver la memoria ni cerrar recursos de forma ordenada en todos los casos, y vuelve a la función imposible de probar de forma aislada: cualquier test que dispare el error mata al proceso de pruebas.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
TestabilidadNo se puede probar el camino de error sin terminar el test.
ReutilizaciónLa función sólo sirve para un programa que siempre aborta.
RecursosSe pierden datos sin guardar y recursos abiertos.
DiseñoSe mezcla la política de la aplicación con la lógica del módulo.

Fundamento en la cátedra

Separa la capa de biblioteca (que informa) de la capa de aplicación (que decide). Se apoya en 0x7003h: No ignores valores de retorno que pueden indicar fallo (verificar y propagar retornos) y en 0x2005h: Cada función debe tener una única responsabilidad (Principio de Responsabilidad Única) (responsabilidad única).

Alcance y excepciones

Aplica a funciones de módulos y TDAs. exit() es aceptable únicamente en main o en una rutina de arranque documentada, y ante condiciones irrecuperables explícitas. En un TAD, jamás.

Ejemplos exhaustivos

❌ Contraejemplo 1 — El TAD decide abortar

pila_t *pila_crear(size_t capacidad)
{
    pila_t *p = malloc(sizeof(*p));
    if (p == NULL) {
        fprintf(stderr, "Sin memoria\n");
        exit(EXIT_FAILURE);
    }
    /* ... */
    return p;
}

Por qué falla: la pila no puede crearse y mata todo el proceso. El llamador no puede informar el error de otra forma ni continuar sin pila.

❌ Contraejemplo 2 — Validación que aborta

void pila_apilar(pila_t *p, int valor)
{
    if (pila_llena(p)) {
        fprintf(stderr, "Pila llena\n");
        exit(EXIT_FAILURE);
    }
    /* ... */
}

Por qué falla: apilar en una pila llena es una condición previsible que el programa de aplicación podría manejar (descartar, avisar, redimensionar), pero el TAD decide por él.

✅ Ejemplo conforme 1 — Retornar el error

pila_t *pila_crear(size_t capacidad)
{
    pila_t *p = malloc(sizeof(*p));
    if (p == NULL) {
        return NULL;
    }
    /* ... */
    return p;
}

El llamador decide si aborta, avisa o reintenta.

✅ Ejemplo conforme 2 — Estado de retorno

typedef enum {
    PILA_OK,
    PILA_LLENA,
    PILA_VACIA
} pila_resultado_t;

pila_resultado_t pila_apilar(pila_t *p, int valor)
{
    if (pila_llena(p)) {
        return PILA_LLENA;
    }
    /* ... */
    return PILA_OK;
}

main traduce el estado a un mensaje y decide la salida:

if (pila_apilar(p, valor) != PILA_OK) {
    fprintf(stderr, "No se pudo apilar\n");
    pila_destruir(p);
    return EXIT_FAILURE;
}

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
grepbuscar exit(/abort( fuera de mainLlamadas en módulos.
cppcheckcppcheck archivo.cUso de exit en bibliotecas.

Checklist de autocontrol

Reglas relacionadas