Error Handling Patterns
Error Handling Fundamentals
Error Handling Workflow
graph TD
A[Potential Error] --> B{Error Detected?}
B -->|Yes| C[Error Handling]
B -->|No| D[Normal Execution]
C --> E[Log Error]
C --> F[Graceful Fallback]
C --> G[Notify User/System]
Error Detection Strategies
Pointer Validation Patterns
// Pattern 1: Early Return
int process_data(int *data) {
if (data == NULL) {
return -1; // Indicate error
}
// Process data
return 0;
}
// Pattern 2: Error Callback
typedef void (*ErrorHandler)(const char *message);
void safe_operation(void *ptr, ErrorHandler on_error) {
if (ptr == NULL) {
on_error("Null pointer detected");
return;
}
// Perform operation
}
Error Handling Techniques
Technique |
Description |
Pros |
Cons |
Return Codes |
Functions return error status |
Simple |
Limited error context |
Error Callbacks |
Pass error handling function |
Flexible |
Complexity |
Exception-like Mechanism |
Custom error management |
Comprehensive |
Overhead |
Comprehensive Error Handling
Structured Error Management
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;
}
Advanced Error Logging
Logging Framework
#include <stdio.h>
void log_error(const char *function, int line, const char *message) {
fprintf(stderr, "Error in %s at line %d: %s\n",
function, line, message);
}
#define LOG_ERROR(msg) log_error(__func__, __LINE__, msg)
// Usage example
void risky_function(int *ptr) {
if (ptr == NULL) {
LOG_ERROR("Null pointer received");
return;
}
}
Error Handling Best Practices
- Detect errors early
- Provide clear error messages
- Log detailed error information
- Use LabEx debugging tools
- Implement graceful degradation
Defensive Programming Techniques
Null Pointer Safe Wrapper
void* safe_pointer_operation(void *ptr, void* (*operation)(void*)) {
if (ptr == NULL) {
fprintf(stderr, "Null pointer passed to operation\n");
return NULL;
}
return operation(ptr);
}
Error Recovery Strategies
stateDiagram-v2
[*] --> Normal
Normal --> ErrorDetected
ErrorDetected --> Logging
ErrorDetected --> Fallback
Logging --> Recovery
Fallback --> Recovery
Recovery --> Normal
Recovery --> [*]
Common Error Scenarios
- Memory allocation failures
- Null pointer dereferences
- Invalid function parameters
- Resource unavailability
Conclusion
Effective error handling requires:
- Proactive error detection
- Clear error communication
- Robust recovery mechanisms
- Comprehensive logging
By implementing these patterns, developers can create more resilient and maintainable C applications.