Defensive Coding Patterns
Introduction to Defensive Programming
Defensive programming is a strategy to minimize potential errors and unexpected behaviors in pointer-based operations.
Memory Management Patterns
// Safe memory allocation wrapper
void* safe_malloc(size_t size) {
void *ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
return ptr;
}
Pointer Safety Workflow
graph TD
A[Pointer Operation] --> B{Null Check}
B -->|Null| C[Error Handling]
B -->|Valid| D[Boundary Check]
D -->|Safe| E[Execute Operation]
D -->|Unsafe| C
Defensive Coding Techniques
Technique |
Description |
Example |
Explicit Initialization |
Always initialize pointers |
int *ptr = NULL; |
Boundary Checking |
Validate memory access |
if (index < array_size) |
Error Handling |
Implement robust error management |
if (ptr == NULL) return ERROR; |
Advanced Defensive Strategies
// Complex pointer validation function
bool is_valid_pointer(void *ptr, size_t expected_size) {
return (ptr != NULL) &&
(ptr >= heap_start) &&
(ptr < heap_end) &&
(malloc_usable_size(ptr) >= expected_size);
}
Memory Cleanup Patterns
// Safe resource management
void process_data(int *data, size_t size) {
if (!is_valid_pointer(data, size * sizeof(int))) {
fprintf(stderr, "Invalid pointer\n");
return;
}
// Process data safely
for (size_t i = 0; i < size; i++) {
// Safe operations
}
}
Error Handling Macros
#define SAFE_FREE(ptr) do { \
if (ptr != NULL) { \
free(ptr); \
ptr = NULL; \
} \
} while(0)
Defensive Coding Best Practices
- Always validate input parameters
- Use const for read-only pointers
- Implement comprehensive error checking
- Minimize pointer arithmetic
LabEx emphasizes that defensive coding is essential for writing robust and reliable C programs.