Patrones de Manejo de Errores
Fundamentos de Manejo de Errores
Flujo de Trabajo de Manejo de Errores
graph TD
A[Posible Error] --> B{¿Error Detectada?}
B -->|Sí| C[Manejo de Error]
B -->|No| D[Ejecución Normal]
C --> E[Registrar Error]
C --> F[Recuperación Alternativa]
C --> G[Notificar al Usuario/Sistema]
Estrategias de Detección de Errores
Patrones de Validación de Punteros
// Patrón 1: Devolución Temprana
int process_data(int *data) {
if (data == NULL) {
return -1; // Indicar error
}
// Procesar datos
return 0;
}
// Patrón 2: Llamada de Devolución de Error
typedef void (*ErrorHandler)(const char *message);
void safe_operation(void *ptr, ErrorHandler on_error) {
if (ptr == NULL) {
on_error("Se detectó un puntero nulo");
return;
}
// Realizar la operación
}
Técnicas de Manejo de Errores
| Técnica |
Descripción |
Pros |
Contras |
| Códigos de Retorno |
Las funciones devuelven un estado de error |
Simple |
Contexto de error limitado |
| Llamadas de Devolución de Error |
Pasar una función de manejo de errores |
Flexible |
Complejidad |
| Mecanismo Similar a Excepciones |
Gestión personalizada de errores |
Completo |
Sobrecarga |
Manejo de Errores Completo
Gestión Estructurada de Errores
typedef enum {
ERROR_NONE,
ERROR_NULL_POINTER,
ERROR_MEMORY_ALLOCATION,
ERROR_INVALID_PARAMETER
} ErrorCode;
typedef struct {
ErrorCode code;
const char *message;
} ErrorContext;
ErrorContext global_error = {ERROR_NONE, NULL};
void set_error(ErrorCode code, const char *message) {
global_error.code = code;
global_error.message = message;
}
void clear_error() {
global_error.code = ERROR_NONE;
global_error.message = NULL;
}
Registro Avanzado de Errores
Marco de Registro
#include <stdio.h>
void log_error(const char *function, int line, const char *message) {
fprintf(stderr, "Error en %s en la línea %d: %s\n",
function, line, message);
}
#define LOG_ERROR(msg) log_error(__func__, __LINE__, msg)
// Ejemplo de uso
void risky_function(int *ptr) {
if (ptr == NULL) {
LOG_ERROR("Se recibió un puntero nulo");
return;
}
}
Mejores Prácticas de Manejo de Errores
- Detectar errores temprano
- Proporcionar mensajes de error claros
- Registrar información detallada de errores
- Usar herramientas de depuración de LabEx
- Implementar degradación gradual
Técnicas de Programación Defensiva
Envoltorio Seguro para Punteros Nulos
void* safe_pointer_operation(void *ptr, void* (*operation)(void*)) {
if (ptr == NULL) {
fprintf(stderr, "Se pasó un puntero nulo a la operación\n");
return NULL;
}
return operation(ptr);
}
Estrategias de Recuperación de Errores
stateDiagram-v2
[*] --> Normal
Normal --> ErrorDetected
ErrorDetected --> Logging
ErrorDetected --> Fallback
Logging --> Recovery
Fallback --> Recovery
Recovery --> Normal
Recovery --> [*]
Escenarios Comunes de Errores
- Fallos de asignación de memoria
- Desreferenciación de punteros nulos
- Parámetros de función inválidos
- No disponibilidad de recursos
Conclusión
El manejo eficaz de errores requiere:
- Detección proactiva de errores
- Comunicación clara de errores
- Mecanismos de recuperación robustos
- Registro completo
Implementando estos patrones, los desarrolladores pueden crear aplicaciones C más resilientes y mantenibles.