Memory Management
Dynamic Memory Allocation
Fundamental Memory Allocation Functions
char *str = malloc(50 * sizeof(char)); // Allocate memory
if (str == NULL) {
// Handle allocation failure
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
// Use the string
strcpy(str, "Hello, LabEx!");
// Always free dynamically allocated memory
free(str);
Memory Allocation Strategies
graph TD
A[Memory Allocation]
A --> B[malloc()]
A --> C[calloc()]
A --> D[realloc()]
A --> E[free()]
Memory Allocation Methods
Function |
Purpose |
Behavior |
malloc() |
Basic allocation |
Uninitialized memory |
calloc() |
Cleared allocation |
Zeros out memory |
realloc() |
Resize allocation |
Preserves existing data |
Safe String Allocation
char* create_string(size_t length) {
char *new_str = malloc((length + 1) * sizeof(char));
if (new_str == NULL) {
return NULL; // Allocation failed
}
new_str[length] = '\0'; // Ensure null termination
return new_str;
}
Memory Leak Prevention
char* process_string(const char* input) {
char* result = malloc(strlen(input) + 1);
if (result == NULL) {
return NULL;
}
strcpy(result, input);
return result;
}
// Proper usage
char* str = process_string("Example");
if (str != NULL) {
// Use string
free(str); // Always free
}
Advanced Memory Management
Reallocating Strings
char* expand_string(char* original, size_t new_size) {
char* expanded = realloc(original, new_size);
if (expanded == NULL) {
free(original); // Free original if realloc fails
return NULL;
}
return expanded;
}
Common Pitfalls
- Forgetting to free allocated memory
- Using memory after freeing
- Buffer overflow
- Incorrect memory size calculations
Best Practices
- Always check allocation results
- Free memory when no longer needed
- Use valgrind for memory leak detection
- Prefer stack allocation when possible
At LabEx, we recommend careful memory management to create robust C programs.
Memory Tracking Technique
typedef struct {
char* data;
size_t size;
} SafeString;
SafeString* create_safe_string(size_t length) {
SafeString* safe_str = malloc(sizeof(SafeString));
if (safe_str == NULL) return NULL;
safe_str->data = malloc(length + 1);
if (safe_str->data == NULL) {
free(safe_str);
return NULL;
}
safe_str->size = length;
safe_str->data[length] = '\0';
return safe_str;
}
void free_safe_string(SafeString* safe_str) {
if (safe_str != NULL) {
free(safe_str->data);
free(safe_str);
}
}