Dynamic Memory in C: malloc, calloc, realloc & free 🧠
Dynamic Memory in C: malloc, calloc, realloc & free is a core C concept covering master dynamic memory allocation in C. Learn the difference between stack and heap memory, how to use malloc, calloc, realloc, and free, and how to avoid memory leaks. This topic is essential for academic learning, board exam preparation, and developing optimized real-world code.
Mentor's Note: Think of the Stack like a small school desk with a fixed size. It is clean and organized, but you cannot fit a giant blueprint on it. The Heap is like renting space in a massive commercial warehouse. You can rent as much space as you want, when you want it, but you are responsible for returning (freeing) the space when you are done. If you don't return it, the warehouse gets full, causing a Memory Leak! 💡
📚 Educational Content: Dynamic memory management is a key topic in GSEB Std 12, CBSE Class 12, and university computer science courses. Questions often focus on the differences between
mallocandcalloc, tracking memory leaks, and safety checks for dynamic allocation.
By the end of this tutorial, you'll know:
- The fundamental difference between Stack memory and Heap memory.
- How to allocate heap memory using
mallocandcalloc. - How to resize allocated blocks using
reallocsafely. - The importance of using
freeto prevent memory leaks and dangling pointers. - How to write safe allocation checks and use tools like Valgrind.
🌟 The Scenario: Booking Hotel Rooms
Imagine you are running a tour group and need to book hotel rooms:
mallocis booking a block of $N$ rooms. The rooms might contain garbage left behind by previous guests.callocis booking $N$ rooms and having room service clean them all to pristine condition (initialized to 0) before you arrive.reallocis realizing mid-trip that your tour group grew. You call the desk to expand your current block of rooms.freeis checking out of the hotel. If you leave without checking out, the rooms stay booked (memory leak), and the hotel runs out of space for other guests!
📖 Stack vs. Heap Memory
Before using allocation functions, it's important to understand the two regions of RAM your program uses:
| Feature | Stack Memory | Heap Memory |
|---|---|---|
| Allocation | Automatic (handled by compiler). | Manual (handled by you). |
| Lifetime | Tied to function scope (destroyed on return). | Persists until explicitly freed. |
| Speed | Extremely fast. | Slower (requires OS requests). |
| Size Limit | Small, fixed size (typically 1MB - 8MB). | Large (limited only by physical RAM). |
| Management | LIFO (Last In, First Out) structure. | Unstructured pool of memory. |
🛠️ Dynamic Allocation Functions (stdlib.h)
All dynamic memory functions are defined in the <stdlib.h> header file.
1. malloc (Memory Allocation)
Allocates a block of raw memory of a specified size in bytes. The memory contains garbage values.
- Syntax:
void* malloc(size_t size); - Example:
int *ptr = (int*)malloc(5 * sizeof(int)); // Allocates space for 5 integers
2. calloc (Contiguous Allocation)
Allocates memory for an array of elements and initializes all bytes to 0.
- Syntax:
void* calloc(size_t num, size_t size); - Example:
int *ptr = (int*)calloc(5, sizeof(int)); // Allocates and clears 5 integers
3. realloc (Re-allocation)
Resizes a previously allocated block of memory. It can expand or shrink the block.
- Syntax:
void* realloc(void* ptr, size_t new_size); - Example:
int *temp = realloc(ptr, 10 * sizeof(int)); // Resizes ptr to hold 10 integers
4. free (De-allocation)
Releases the allocated heap memory back to the operating system.
- Syntax:
void free(void* ptr);
🛡️ Writing Safe Allocation Code
Dynamic memory allocation can fail if the operating system runs out of RAM. When this happens, allocation functions return NULL.
Never dereference a pointer returned by malloc, calloc, or realloc without checking if it is NULL first. Attempting to write to a NULL pointer causes a segmentation fault.
int *ptr = malloc(100 * sizeof(int));
if (ptr == NULL) {
printf("Memory Allocation Failed!");
exit(1); // Exit program
}
If realloc fails, it returns NULL but leaves the original memory block intact. If you write ptr = realloc(ptr, new_size), and it fails, ptr becomes NULL. This loses the address of the original block, causing a memory leak.
Always use a temporary pointer for realloc!
int *temp = realloc(ptr, new_size);
if (temp != NULL) {
ptr = temp; // Safe to reassign
} else {
// Handle error (original 'ptr' is still valid)
}
🔍 Memory Leaks and Valgrind
A Memory Leak occurs when you allocate heap memory but lose the pointer referencing it before calling free(). The memory remains blocked, and if your program runs for a long time (like a server), it will eventually consume all system RAM and crash.
To find memory leaks on Linux systems, you can use Valgrind:
gcc -g program.c -o program
valgrind --leak-check=full ./program
Valgrind tracks every allocation and deallocation and reports any unfreed memory blocks.
🧠 Algorithm & Step-by-Step Logic
Traced dynamic memory management:
- Start 🏁
- Request size $N$ from the user.
- Allocate memory using
mallocfor $N$ integers. - Check
if (ptr == NULL). If yes, terminate. - Populate the array with values.
- Resize the array to $2N$ using
reallocwith a temporary pointer. - Verify the resize succeeded.
- Free the memory using
free(ptr). - Set
ptr = NULLto avoid dangling references. - End 🏁
💻 Implementation (C99)
This program shows how to safely allocate, resize, and free memory in C.
#include <stdio.h>
#include <stdlib.h>
// 🛒 Scenario: Dynamic Grade Register
// 🚀 Action: Showcase safe malloc, calloc, realloc, and free implementation
int main() {
int n = 3;
// 1. Allocating using calloc (Initializes all elements to 0)
printf("1. Allocating memory for %d students using calloc:\n", n);
int *grades = (int*)calloc(n, sizeof(int));
// Safety check
if (grades == NULL) {
printf(" Error: Memory allocation failed!\n");
return 1;
}
// Print values to verify zero-initialization
for (int i = 0; i < n; i++) {
printf(" Student %d Grade: %d\n", i + 1, grades[i]);
}
printf("\n");
// Populate initial grades
grades[0] = 85;
grades[1] = 90;
grades[2] = 95;
// 2. Resizing using realloc (Expanding to hold 5 students)
int new_size = 5;
printf("2. Resizing memory to hold %d students using realloc:\n", new_size);
// Always use a temporary pointer to prevent memory leaks if realloc fails
int *temp_grades = (int*)realloc(grades, new_size * sizeof(int));
if (temp_grades != NULL) {
grades = temp_grades; // Safe reallocation successful
printf(" Reallocation successful! Adding new students.\n");
grades[3] = 88;
grades[4] = 92;
} else {
printf(" Error: Reallocation failed! Original memory preserved.\n");
free(grades);
return 1;
}
// Print all grades
for (int i = 0; i < new_size; i++) {
printf(" Student %d Grade: %d\n", i + 1, grades[i]);
}
printf("\n");
// 3. Deallocating memory using free
printf("3. Releasing memory...\n");
free(grades);
grades = NULL; // Prevent dangling pointer bug
printf(" Memory successfully freed.\n");
return 0;
}
// Output:
// 1. Allocating memory for 3 students using calloc:
// Student 1 Grade: 0
// Student 2 Grade: 0
// Student 3 Grade: 0
//
// 2. Resizing memory to hold 5 students using realloc:
// Reallocation successful! Adding new students.
// Student 1 Grade: 85
// Student 2 Grade: 90
// Student 3 Grade: 95
// Student 4 Grade: 88
// Student 5 Grade: 92
//
// 3. Releasing memory...
// Memory successfully freed.
📊 Sample Dry Run
Let's trace the memory actions step-by-step:
Assume base address returned by calloc is 0x5000.
| Step | Operation | Pointer Value | Heap Status | Description |
|---|---|---|---|---|
| 1 | calloc(3, sizeof(int)) | 0x5000 | 12 bytes allocated (all zeroed). | Initial array setup. |
| 2 | realloc(grades, 5 * sizeof(int)) | 0x5000 | Block extended to 20 bytes. | Array extended (no address change if contiguous space is available). |
| 3 | free(grades) | 0x5000 (dangling) | 20 bytes released back to OS. | Memory is freed, but pointer still holds address. |
| 4 | grades = NULL | NULL | Safe state. | Pointer cleared to prevent accidental access. |
📉 Complexity Analysis
Time Complexity ⏱️
malloc/calloc: $O(1)$ typical time complexity (though heap search algorithms vary by OS).realloc: $O(N)$ worst-case time complexity, as it may need to copy all existing elements to a new physical address if the current block cannot be expanded in-place.free: $O(1)$ time complexity.
Space Complexity 💾
- Auxiliary Space: $O(1)$ auxiliary space.
- Total Space: $O(N)$ space in the heap, where $N$ is the number of elements allocated.
🎨 Visual Logic & Diagrams
The diagram below shows how stack variables point to dynamic memory blocks in the heap:
🎯 Practice Problems
Easy Level 🟢
- Problem 1: Write a program to dynamically allocate memory for a single structure (e.g.
Bookwith title and price) usingmallocand print its values. - Problem 2: Implement a program that allocates space for an array of 5 characters using
callocand verifies that they are zero-initialized (empty characters).
Medium Level 🟡
- Problem 3: Write a program that reads numbers from a user dynamically. Start by allocating space for 2 integers, and use
reallocto double the size of the array every time the limit is reached. - Problem 4: Write a function that takes a dynamically allocated integer array and returns a new dynamically allocated array containing only the even numbers from the original array.
Hard Level 🔴
- Problem 5: Build a dynamic string builder. Implement functions
create_str(),append_str(), andfree_str(). The append function should automatically resize the underlying buffer usingreallocto accommodate new strings.
❓ Frequently Asked Questions
Q: What is the difference between malloc and calloc?
malloc takes a single argument (total bytes to allocate) and leaves memory uninitialized (containing random garbage). calloc takes two arguments (number of elements and size of each element) and clears the allocated memory block to zero.
Q: Why do I need to write (int*) before malloc? Is casting required?
In standard C, casting the return value of malloc (which is void*) is optional because void* is automatically promoted to other pointer types. However, casting is required in C++ and makes the code clearer for developer inspection.
Q: What is a double free error?
A double free occurs when you call free() on the same memory address twice. This corrupts the heap management structures and causes the program to crash. Setting pointers to NULL after freeing them is the best way to prevent double free bugs, as calling free(NULL) is safe and does nothing.
✅ Summary
In this tutorial, you've learned:
- ✅ Stack memory is managed automatically; Heap memory must be managed manually.
- ✅
mallocallocates raw memory;callocallocates and initializes memory to zero. - ✅
reallocresizes dynamic blocks, but must be checked using temporary pointers. - ✅
freereleases heap allocations to prevent memory leaks. - ✅ Clear pointers to
NULLimmediately after freeing them to avoid dangling pointer bugs.
💡 Interview Tips & Board Focus 👔
Common Questions
- "What is a memory leak, and how do you detect it?"
- "What happens if you do not check the return value of
malloc?" - "Compare Stack vs Heap allocation."
Answering Strategy
- Always point out that forgetting to call
free()leads to memory leaks. This is a common exam topic. - Mention Valgrind as the industry standard tool for identifying memory leaks and memory corruption errors on Linux platforms.
📚 Best Practices & Common Mistakes
✅ Best Practices
- Check the return values of all dynamic memory allocation calls for
NULL. - Match every call to
malloc,calloc, orreallocwith exactly one call tofree(). - Set pointers to
NULLimmediately after callingfree()to prevent dangling pointer bugs.
❌ Common Mistakes ⚠️
- Dangling Pointer Access: Trying to access or write to a pointer after it has been freed.
- Overwriting Pointer Address: Writing code like
ptr = malloc(size);without callingfree(ptr)first, which leaks the previous block. - Forgetting
sizeof: Writingmalloc(5)when you want 5 integers, which only allocates 5 bytes (instead of 20 bytes).
📚 Further Reading
Continue your learning path:
Guide Version: 2.0
Purpose: Educational content creation standards for VD Computer Tuition