BCA SCHOOL
Programming Tutorials • Notes • Practical • Books
LATEST TUTORIALS

Memory Allocation Functions in C: malloc, calloc, realloc, free | Unit 3 | BKNMU BCA

by BCA School



BKNMU Junagadh  |  BCA Sem 1  |  Unit 3

Dynamic Memory Allocation in C: malloc, calloc, realloc & free

Complete Guide to Heap Memory Management, Contiguous Block Allocation, and Dynamic Resizing

BKNMU Junagadh BCA Sem 1 Unit 3 stdlib.h Header Dynamic Memory Allocation Heap Memory
In simple words: Static memory allocation fixes variable and array sizes at compile time in the stack segment, leading to either memory wastage or shortage. Dynamic Memory Allocation (DMA) allows a C program to allocate, resize, and release memory from the Heap segment at runtime as needed. Defined within #include <stdlib.h>, the four essential routines are malloc(), calloc(), realloc(), and free(), tailored here for BKNMU BCA Semester 1 (Unit 3).
📖 Core Dynamic Memory Allocation Functions

The heap management system provides four core operations to handle dynamic memory buffers:

malloc()

1. Single Block Allocation

Allocates a single continuous block of specified bytes on the heap. Memory contents remain uninitialized and contain garbage values.

calloc()

2. Contiguous Zero Allocation

Allocates multiple blocks for elements and automatically initializes every allocated byte to zero (clearing garbage data).

realloc()

3. Dynamic Block Resizing

Modifies the size of a previously allocated memory block, either expanding or shrinking it while preserving existing data contents.

free()

4. Memory Deallocation

Releases allocated heap memory back to the operating system, preventing memory leaks and avoiding dangling memory references.

1️⃣ Master Table: Function Specifications & Prototypes

A complete reference of function prototypes, operational behavior, and return values:

Function Prototype Functional Purpose Return Value / Type
void* malloc(size_t size) Allocates a single uninitialized memory block of size bytes on the heap. Returns void* pointer to base address (or NULL on failure).
void* calloc(size_t n, size_t s) Allocates contiguous memory for n elements of size s each, initializing all bytes to zero. Returns void* pointer to base address (or NULL on failure).
void* realloc(void *ptr, size_t s) Resizes an existing memory block pointed to by ptr to a new size of s bytes. Returns void* pointer to new base address (or NULL on failure).
void free(void *ptr) Deallocates memory block previously allocated by malloc, calloc, or realloc. Takes memory base pointer. Returns nothing (void).
ℹ️ Core Concepts of Dynamic Memory:
  • Generic Pointer (void*): All allocation functions return a generic void* pointer, which must be typecasted to the appropriate data type pointer (e.g., (int*)malloc(...)).
  • Allocation Failure Check: If system heap memory is exhausted, functions return NULL. Always verify pointers against NULL before accessing them.
  • sizeof Operator: Always calculate byte requirements using sizeof(data_type) to guarantee cross-platform architecture portability.
💻 Practical Code Examples

1. Dynamic Array Creation using malloc() and Zero-Initialized Allocation using calloc():

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

int main() {
    int *arr_m, *arr_c;
    int n = 3;

    // 1. malloc: Allocates bytes, holds garbage values
    arr_m = (int*) malloc(n * sizeof(int));

    // 2. calloc: Allocates 3 contiguous blocks, initialized to 0
    arr_c = (int*) calloc(n, sizeof(int));

    if (arr_m == NULL || arr_c == NULL) {
        printf("Memory allocation error!\n");
        exit(1);
    }

    printf("calloc default element 0: %d\n", arr_c[0]); // Prints 0

    // Release both heap blocks
    free(arr_m);
    free(arr_c);

    return 0;
}

2. Expanding Dynamic Memory using realloc():

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

int main() {
    int *ptr;

    // Initial allocation for 2 integers
    ptr = (int*) malloc(2 * sizeof(int));
    ptr[0] = 10;
    ptr[1] = 20;

    // Reallocating to expand size from 2 elements to 4 elements
    int *temp = (int*) realloc(ptr, 4 * sizeof(int));

    if (temp != NULL) {
        ptr = temp;
        ptr[2] = 30;
        ptr[3] = 40;

        printf("Resized Array Elements: %d %d %d %d\n", 
               ptr[0], ptr[1], ptr[2], ptr[3]);
    }

    free(ptr);
    ptr = NULL; // Prevent dangling pointer

    return 0;
}
🔄 Step-by-Step Flow: Dynamic Memory Lifecycle
1

Step 1: Heap Allocation Request

Calling malloc() or calloc() requests memory from the operating system heap and returns the starting base byte address.

2

Step 2: Runtime Access & Resizing

Pointers read and write dynamically to allocated heap offsets. If capacity needs to grow, realloc() extends or relocates the block seamlessly.

3

Step 3: Heap Cleanup & Pointer Reset

Calling free() returns the block back to the heap pool. Assigning ptr = NULL; neutralizes dangling pointer vulnerabilities.

💡 Critical Exam Difference: malloc vs calloc:
  • malloc() accepts 1 argument (total bytes) and does not initialize memory (retains garbage values).
  • calloc() accepts 2 arguments (number of elements, size per element) and initializes all bytes to 0.
⚠️ Memory Leak & Dangling Pointer Warning:
  • Memory Leak: Occurs when heap memory is allocated but never freed with free(), causing available RAM to deplete.
  • Dangling Pointer: Occurs when a pointer continues to point to deallocated memory after free(ptr). Always write ptr = NULL; immediately after freeing.
📝 Quick Revision — Key Exam Points
  • Header: #include <stdlib.h>
  • malloc(size): Allocates uninitialized memory chunk; contains garbage.
  • calloc(n, size): Allocates multiple blocks initialized to zero.
  • realloc(ptr, new_size): Modifies existing allocated block size dynamically.
  • free(ptr): Releases heap memory back to OS to prevent memory leaks.
  • NULL Check: Always verify if pointer equals NULL before using.