Practical Coding Patterns
Dynamic Array Implementation Patterns
Pattern 1: Safe Memory Allocation
int* create_dynamic_array(int size) {
int* array = malloc(size * sizeof(int));
if (array == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
return array;
}
Pattern 2: Flexible Array Resizing
int* resize_array(int* original, int old_size, int new_size) {
int* resized = realloc(original, new_size * sizeof(int));
if (resized == NULL) {
free(original);
fprintf(stderr, "Memory reallocation failed\n");
exit(1);
}
return resized;
}
Memory Management Workflow
graph TD
A[Initialize Array] --> B[Allocate Memory]
B --> C{Allocation Successful?}
C -->|Yes| D[Use Array]
C -->|No| E[Handle Error]
D --> F[Modify/Resize Array]
F --> G[Free Memory]
Best Practices Comparison
Practice |
Recommendation |
Example |
Memory Allocation |
Always check allocation |
Use NULL pointer check |
Memory Freeing |
Free memory explicitly |
Call free() when done |
Error Handling |
Provide fallback mechanisms |
Implement error recovery |
Pattern 3: Dynamic 2D Array Creation
int** create_2d_array(int rows, int cols) {
int** array = malloc(rows * sizeof(int*));
if (array == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
for (int i = 0; i < rows; i++) {
array[i] = malloc(cols * sizeof(int));
if (array[i] == NULL) {
// Clean up previous allocations
for (int j = 0; j < i; j++) {
free(array[j]);
}
free(array);
exit(1);
}
}
return array;
}
Memory Safety Techniques
- Always validate memory allocations
- Use consistent error handling
- Implement proper memory cleanup
- Avoid memory leaks
Pattern 4: Memory Cleanup Function
void free_2d_array(int** array, int rows) {
for (int i = 0; i < rows; i++) {
free(array[i]);
}
free(array);
}
Advanced Allocation Strategies
graph LR
A[Memory Allocation] --> B{Allocation Type}
B --> |Small, Fixed| C[Stack Allocation]
B --> |Dynamic, Varying| D[Heap Allocation]
B --> |Large Datasets| E[Memory Mapping]
LabEx Recommendation
LabEx suggests practicing these patterns in controlled development environments to build robust memory management skills.
- Minimize frequent reallocations
- Estimate initial array size
- Use memory pools for repetitive allocations
Conclusion
Mastering practical coding patterns for dynamic memory management is crucial for writing efficient and reliable C programs.