Skip to main content

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 malloc and calloc, tracking memory leaks, and safety checks for dynamic allocation.

What You'll Learn

By the end of this tutorial, you'll know:

  • The fundamental difference between Stack memory and Heap memory.
  • How to allocate heap memory using malloc and calloc.
  • How to resize allocated blocks using realloc safely.
  • The importance of using free to 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:

  • malloc is booking a block of $N$ rooms. The rooms might contain garbage left behind by previous guests.
  • calloc is booking $N$ rooms and having room service clean them all to pristine condition (initialized to 0) before you arrive.
  • realloc is realizing mid-trip that your tour group grew. You call the desk to expand your current block of rooms.
  • free is 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:

FeatureStack MemoryHeap Memory
AllocationAutomatic (handled by compiler).Manual (handled by you).
LifetimeTied to function scope (destroyed on return).Persists until explicitly freed.
SpeedExtremely fast.Slower (requires OS requests).
Size LimitSmall, fixed size (typically 1MB - 8MB).Large (limited only by physical RAM).
ManagementLIFO (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.

Always Check for 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
}
Use a Temp Pointer for realloc

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:

  1. Start 🏁
  2. Request size $N$ from the user.
  3. Allocate memory using malloc for $N$ integers.
  4. Check if (ptr == NULL). If yes, terminate.
  5. Populate the array with values.
  6. Resize the array to $2N$ using realloc with a temporary pointer.
  7. Verify the resize succeeded.
  8. Free the memory using free(ptr).
  9. Set ptr = NULL to avoid dangling references.
  10. 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.

StepOperationPointer ValueHeap StatusDescription
1calloc(3, sizeof(int))0x500012 bytes allocated (all zeroed).Initial array setup.
2realloc(grades, 5 * sizeof(int))0x5000Block extended to 20 bytes.Array extended (no address change if contiguous space is available).
3free(grades)0x5000 (dangling)20 bytes released back to OS.Memory is freed, but pointer still holds address.
4grades = NULLNULLSafe 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. Book with title and price) using malloc and print its values.
  • Problem 2: Implement a program that allocates space for an array of 5 characters using calloc and 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 realloc to 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(), and free_str(). The append function should automatically resize the underlying buffer using realloc to 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.
  • malloc allocates raw memory; calloc allocates and initializes memory to zero.
  • realloc resizes dynamic blocks, but must be checked using temporary pointers.
  • free releases heap allocations to prevent memory leaks.
  • ✅ Clear pointers to NULL immediately 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, or realloc with exactly one call to free().
  • Set pointers to NULL immediately after calling free() 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 calling free(ptr) first, which leaks the previous block.
  • Forgetting sizeof: Writing malloc(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

📍 Visit Us

🏫 VD Computer Tuition Surat

VD Computer Tuition
📍 Address
2/66 Faram Street, Rustompura
Surat395002, Gujarat, India
📞 Phone / WhatsApp
+91 84604 41384
🌐 Website

Computer Classes & Tuition — Areas We Serve in Surat

AdajanAlthanAmroliAthwaAthwalinesBhagalBhatarBhestanCanal RoadChowkCitylightDumasGaurav PathGhod Dod RoadHaziraJahangirpuraKamrejKapodraKatargamLimbayatMagdallaMajura GateMota VarachhaNanpuraNew CitylightOlpadPalPandesaraParle PointPiplodPunaRanderRing RoadRustampuraSachinSalabatpuraSarthanaSosyo CircleUdhnaVarachhaVed RoadVesuVIP Road
📞 Call Sir💬 WhatsApp Sir