100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C

Dynamic Memory Allocation in C

Master C dynamic memory allocation with malloc, calloc, realloc, and free, including sizing, zero-initialization, and leak prevention.

File Handling & PreprocessorIntermediate13 min readJul 7, 2026
Analogies

1. Introduction

Dynamic memory allocation lets a C program request memory from the heap at run time, rather than fixing array sizes at compile time. This is essential when the amount of data needed is unknown in advance — for example, reading a variable number of records from a file, building a linked list, or resizing a buffer as input grows. The C standard library (stdlib.h) provides four core functions for this: malloc(), calloc(), realloc(), and free(). Because the programmer is fully responsible for managing this memory, understanding exactly what each function guarantees is critical to writing correct, leak-free code.

🏏

Cricket analogy: A stadium doesn't fix seating capacity at construction; if a bigger crowd than expected shows up for an India-Pakistan match, organizers dynamically add temporary stands, just as malloc lets a program request more heap memory at run time instead of a fixed compile-time array.

2. Syntax

c
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t new_size);
void free(void *ptr);

3. Explanation

malloc(size) allocates a single block of size bytes from the heap and returns a void* to it, or NULL if allocation fails; the contents of the memory are uninitialized (indeterminate garbage values). calloc(nmemb, size) allocates space for nmemb elements of size bytes each (total nmemb * size bytes) and, unlike malloc(), guarantees the entire block is zero-initialized — this makes it well-suited for arrays that need a clean starting state. realloc(ptr, new_size) resizes a previously allocated block: it may extend the block in place if there is room, or it may allocate a new block elsewhere, copy the old contents over, and free the original — so the caller must always use the pointer realloc() returns (never assume the original pointer is still valid), and must check for NULL before overwriting the original pointer, since a failed realloc() leaves the original block untouched but returns NULL. free(ptr) releases a block previously returned by malloc/calloc/realloc back to the heap; passing anything else (including an already-freed pointer) is undefined behavior. Every successful allocation must eventually be matched with exactly one free().

🏏

Cricket analogy: malloc is like reserving a fresh, unmarked scoreboard with garbage numbers still showing from the last match until someone updates it; calloc is like a groundstaff wiping the scoreboard to all zeros before play starts, guaranteeing a clean state; realloc is like expanding the stand to more seats, possibly moving the whole section elsewhere and copying the existing spectators over, so you must trust the new seating chart, not the old one; free is like tearing down temporary stands after the match, and reusing torn-down seats without permission is undefined chaos.

4. Example

c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n = 5;
    int *arr = (int *)calloc(n, sizeof(int)); /* zero-initialized */
    if (arr == NULL) {
        fprintf(stderr, "Allocation failed\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        arr[i] = i * i;
    }

    /* Grow the array to hold 8 elements */
    int *temp = (int *)realloc(arr, 8 * sizeof(int));
    if (temp == NULL) {
        fprintf(stderr, "Reallocation failed\n");
        free(arr);
        return 1;
    }
    arr = temp;

    for (int i = n; i < 8; i++) {
        arr[i] = i * i;
    }

    for (int i = 0; i < 8; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);
    arr = NULL;
    return 0;
}

5. Output

text
0 1 4 9 16 25 36 49

Watch out for three classic bugs: (1) memory leaks — forgetting to call free() on every allocated block, especially along early-return error paths; (2) dangling pointers — using a pointer after it has been freed, or freeing it twice; free the memory and then set the pointer to NULL to guard against accidental reuse; (3) skipping the NULL check after malloc()/calloc()/realloc() — dereferencing a NULL pointer on allocation failure crashes the program.

Always use realloc()'s return value assigned to a temporary pointer first (as in temp = realloc(arr, ...)), not directly to the original pointer — if realloc() fails and returns NULL, overwriting the original pointer would leak the still-valid original block and lose your only reference to it.

6. Key Takeaways

  • malloc() allocates uninitialized memory; calloc() allocates and zero-initializes memory.
  • realloc() may move the block to a new address — always use its return value, and check for NULL before discarding the original pointer.
  • free() must be called exactly once per successful allocation to avoid memory leaks.
  • Always check malloc/calloc/realloc return values for NULL before dereferencing.
  • Set pointers to NULL after freeing them to avoid dangling-pointer bugs and accidental double frees.

Practice what you learned

Was this page helpful?

Topics covered

#CProgrammingStudyNotes#Programming#DynamicMemoryAllocationInC#Dynamic#Memory#Allocation#Syntax#StudyNotes#SkillVeris#ExamPrep