Avoiding Memory Errors
Common Memory Errors in C
1. Memory Leaks
Memory leaks occur when dynamically allocated memory is not properly freed.
void memory_leak_example() {
int *ptr = malloc(sizeof(int));
// Missing free(ptr) - causes memory leak
}
2. Dangling Pointers
Pointers that reference memory that has been freed or is no longer valid.
int* create_dangling_pointer() {
int* ptr = malloc(sizeof(int));
free(ptr);
return ptr; // Dangerous - returning freed memory
}
Memory Error Prevention Strategies
Pointer Validation Techniques
void safe_memory_allocation() {
int *ptr = malloc(sizeof(int));
// Always check allocation
if (ptr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
// Use memory
*ptr = 42;
// Always free
free(ptr);
ptr = NULL; // Set to NULL after freeing
}
Memory Management Workflow
graph TD
A[Allocate Memory] --> B{Allocation Successful?}
B -->|Yes| C[Validate Pointer]
B -->|No| D[Handle Error]
C --> E[Use Memory Safely]
E --> F[Free Memory]
F --> G[Set Pointer to NULL]
Best Practices Checklist
Practice |
Description |
Example |
Null Check |
Validate memory allocation |
if (ptr == NULL) |
Immediate Free |
Free when no longer needed |
free(ptr) |
Pointer Reset |
Set to NULL after freeing |
ptr = NULL |
Bounds Checking |
Prevent buffer overflows |
Use array bounds |
Advanced Error Prevention Techniques
1. Smart Pointer Patterns
typedef struct {
int* data;
size_t size;
} SafeBuffer;
SafeBuffer* create_safe_buffer(size_t size) {
SafeBuffer* buffer = malloc(sizeof(SafeBuffer));
if (buffer == NULL) return NULL;
buffer->data = malloc(size * sizeof(int));
if (buffer->data == NULL) {
free(buffer);
return NULL;
}
buffer->size = size;
return buffer;
}
void free_safe_buffer(SafeBuffer* buffer) {
if (buffer != NULL) {
free(buffer->data);
free(buffer);
}
}
Tool |
Purpose |
Key Features |
Valgrind |
Memory leak detection |
Comprehensive memory analysis |
AddressSanitizer |
Runtime memory error detection |
Finds use-after-free, buffer overflows |
Common Pitfalls to Avoid
- Never use a pointer after freeing
- Always match
malloc()
with free()
- Check return values of memory allocation functions
- Avoid multiple frees of the same pointer
Error Handling Example
#include <stdio.h>
#include <stdlib.h>
int* safe_integer_array(size_t size) {
// Comprehensive error handling
if (size == 0) {
fprintf(stderr, "Invalid array size\n");
return NULL;
}
int* arr = malloc(size * sizeof(int));
if (arr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return NULL;
}
return arr;
}
At LabEx, we emphasize the importance of rigorous memory management practices to write robust and efficient C programs.
Conclusion
Proper memory management is crucial for writing safe and efficient C programs. Always validate, carefully manage, and properly free dynamically allocated memory.