El manejo de errores en el lenguaje C siempre ha sido una tarea del desarrollador. En la biblioteca estándar no hay excepciones; los errores se devuelven a través de códigos de retorno o de la variable global errno (comienzo de su uso: UNIX de los años 70, luego POSIX y ANSI C). Estos mecanismos todavía se utilizan hoy en día para gestionar el flujo de ejecución en situaciones anormales.
Los errores al trabajar con funciones estándar (operaciones de archivos, asignación de memoria, funciones de cadenas) pueden ser imperceptibles sin un control especial. Un manejo incorrecto — ignorar el código de retorno, interpretar incorrectamente errno, falta de limpieza de recursos — conduce a un funcionamiento incorrecto del programa, caídas y vulnerabilidades.
El manejo correcto de errores requiere un análisis obligatorio de los valores devueltos por las funciones, el uso de errno solo inmediatamente después de un fallo y la salida informativa de errores. Los códigos de retorno son preferibles para funciones internas, ya que permiten manejar errores sin efectos secundarios globales. errno se aplica con más frecuencia a las llamadas del sistema y a funciones de la biblioteca estándar. Después de cada operación potencialmente peligrosa, se analiza el retorno, y el estado global (errno) no debe ser sobrescrito por llamadas intermedias.
Ejemplo de código:
#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Error: %s ", strerror(errno)); } return f; }
Características clave:
¿Se puede usar errno para funciones de usuario si se quiere pasar errores hacia arriba?
No, errno está destinada solo para funciones de biblioteca estándar y llamadas del sistema. Es global, puede ser sobrescrita en cualquier punto y no es adecuada para funciones propias.
¿Es obligatorio establecer errno antes de cada llamada a una función?
No, pero se recomienda restablecer errno (por ejemplo, a cero) antes de las llamadas, si se planea analizar cambios. No cada función modifica errno en caso de éxito, solo en caso de error.
eno = 0; ... llamada a una función peligrosa ...
¿Se puede confiar en errno después de cualquier función?
Solo para aquellas funciones que, según el estándar, la establecen explícitamente en caso de falla. Muchas funciones de la biblioteca estándar no tocan errno en caso de éxito. La documentación es tu amiga.
Abrir un archivo sin verificar el resultado, los errores no se analizan, el programa funciona incorrectamente cuando falta el archivo:
Pros:
Contras:
Después de cada función crítica, se verifica el resultado; en caso de error, se imprime un mensaje detallado con strerror(errno), la ejecución se completa correctamente:
Pros:
Contras: