CS Atlas GATE 2027
PDS course
0 / 103 complete

PDS/Phase 1 · Programming in C

Lesson 1.7 · Item 31 of 103

Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Read at your own pace. Try the questions before opening the answers.

On this page

0 · Recall Warm-up

Answer from memory first. Answers are in the Answer Vault at the bottom.

1 · The Hook

🎣

A wedding caterer does not know until the morning whether 80 or 800 guests will come. Reserving tables for 800 every time wastes space; reserving 80 might be too few. Programs face the same problem: the amount of data is often known only while the program runs. So C lets a program ask for memory at run time, exactly as much as it needs, and hand it back later.

2 · Predict First

🤔

A function creates int local = 5; and returns &local. The caller then prints *p. Is 5 guaranteed? Make a guess in your head. The answer opens Section 3.

3 · Core Concept

💡

Predict First — the answer

No. local lived in the function’s stack frame, which is popped on return. The pointer now points to dead memory: a dangling pointer. Reading it is undefined behavior. Memory from malloc does not have this problem.

The heap

Besides code, statics/globals and the stack, a program has a fourth region, the heap: a pool of memory handed out on request. Heap memory lives until the program explicitly frees it, regardless of which function asked for it.

malloc, calloc, realloc, free

Call (stdlib.h)Does
malloc(n)reserves n bytes, contents garbage; returns a void * (convertible to any pointer type) or NULL if it fails
calloc(k, size)reserves k × size bytes, all set to 0
realloc(p, n)resizes the block to n bytes, keeping the old contents; may move it and return a new address
free(p)gives the block back; p itself still holds the old address
int n = 5, i;
int *a = malloc(n * sizeof(int));
if (a == NULL) return 1;
for (i = 0; i < n; i++)
    a[i] = i * i;
printf("%d %d\n", a[2], a[4]);
free(a);

Output

4 16

Always use sizeof (n * sizeof(int)), and check for NULL.

int *c = calloc(4, sizeof(int));
int *m = malloc(2 * sizeof(int));
m[0] = 7; m[1] = 8;
m = realloc(m, 4 * sizeof(int));
m[2] = 9; m[3] = 10;
printf("%d %d %d %d | %d %d %d %d\n", c[0], c[1], c[2], c[3], m[0], m[1], m[2], m[3]);
free(c);
free(m);

Output

0 0 0 0 | 7 8 9 10

Stack vs heap

Stack (automatic)Heap (dynamic)
Createdon entering a block/callby malloc/calloc/realloc
Destroyedautomatically on leavingonly by free
Sizefixed when compiledchosen at run time
Speedvery fastslower (bookkeeping)
Typical bugreturning the address of a localleaks, dangling pointers, double free

Returning heap memory is fine

int *makeArray(int n)
{
    int *p = malloc(n * sizeof(int));
    int i;
    for (i = 0; i < n; i++)
        p[i] = 10 * (i + 1);
    return p;                 /* fine: heap memory outlives the call */
}

int main(void)
{
    int *v = makeArray(3);
    printf("%d %d %d\n", v[0], v[1], v[2]);
    free(v);
    return 0;
}

Output

10 20 30

The three classic bugs

  • Dangling pointer: a pointer to memory that no longer exists (freed heap block, or a popped stack frame). Using it is undefined behavior. Setting p = NULL after free helps.
  • Memory leak: losing the last pointer to a block without freeing it (p = malloc(…); p = malloc(…);). The block can never be freed; long-running programs slowly run out of memory.
  • Double free: calling free twice on the same block: undefined behavior. Watch out when two pointers share one block.

A 2-D table built at run time

An array of row pointers, each row a separate block:

int rows = 3, cols = 4, i, j;
int **g = malloc(rows * sizeof(int *));
for (i = 0; i < rows; i++)
    g[i] = malloc(cols * sizeof(int));
for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
        g[i][j] = i * cols + j;
printf("%d %d\n", g[2][1], g[1][3]);
for (i = 0; i < rows; i++)
    free(g[i]);
free(g);

Output

9 7

Free the rows first, then the array of row pointers.

4 · Visual

Diagram: Code · machine instructions · Static data · globals and statics · Heap ↑ · malloc’d blocks; you free them · (free space) · heap and stack grow towards each other · Stack ↓ · frames: pushed on call, popped on return · process memory (3D view)

The four regions of a running C program (a common layout; the exact arrangement depends on the system).

Memory leak:                          Dangling pointer after free:

p = malloc(16);  p --> [block A]      int *p = malloc(4);  p --> [block]
p = malloc(16);  p --> [block B]      int *q = p;          q --> [block]
                       [block A]  <-- free(p);             p, q --> [freed!]
             nobody points here:      *q = 1;   undefined behavior (q dangles)
             it can never be freed    free(q);  undefined: double free

Leaks lose memory; dangling pointers and double frees corrupt it.

5 · Worked Examples

Example 1 Easy

What does this print?

int n = 5, i;
int *a = malloc(n * sizeof(int));
if (a == NULL) return 1;
for (i = 0; i < n; i++)
    a[i] = i * i;
printf("%d %d\n", a[2], a[4]);
free(a);

Solution

a[i] = i²: a[2] = 4, a[4] = 16.

Output

4 16

Example 2 Medium

Which function is correct, and what is wrong with the others?

int *f1(void) { int x = 7; return &x; }
int *f2(void) { int *p = malloc(sizeof(int)); *p = 7; return p; }
int *f3(void) { static int y = 7; return &y; }
int *f4(void) { int *p = malloc(sizeof(int)); *p = 7; free(p); return p; }

Solution

f2 and f3 are correct: heap memory and static variables both outlive the call. f1 returns the address of a local in a popped frame (dangling). f4 frees the block and then returns a dangling pointer.

Example 3 GATE

What does this print, and what does the code at the end protect against?

int *p = malloc(sizeof(int));
int *q = p;
*q = 42;
printf("%d\n", *p);
free(p);
p = NULL;
q = NULL;

Solution

q is a second name for the same block: *q = 42 makes *p 42. After free(p) both pointers dangle; setting both to NULL ensures nobody uses or frees the block again.

Output

42

6 · GATE Traps

⚠️

  • malloc does not zero memory; calloc does.
  • realloc may move the block: always use its return value.
  • free(p) does not change p; it now dangles. Set it to NULL.
  • Freeing a block reached through two pointers once is enough; freeing it twice is undefined.
  • Returning the address of an automatic local gives a dangling pointer; returning malloc’d or static memory is fine.
  • Every malloc needs exactly one matching free, or the memory leaks.

8 · Memory Hook

🧠

“The stack cleans up after you; the heap never does.” Heap memory is a library book: borrow (malloc), use it, return it (free) exactly once, and never read a book you already returned.

9 · Connect the Dots

Lesson 1.6 built self-referential records; now they can be created one by one while the program runs. The C phase ends with two tools that work before and around the compiler. Next lesson answers: how can text be replaced in the program before it is compiled, and how can a function be stored in a variable?

10 · Self-Test

GATE format. Try every question before opening the vault.

Q1MCQ1 markcalloc

What does calloc(5, sizeof(int)) give?

  • (A) 20 bytes, all zero (4-byte ints)
  • (B) 20 bytes, garbage
  • (C) 5 ints, each 5
  • (D) 5 bytes, garbage

Q2MCQ2 marksDangling

Which function returns a pointer that is safe to use?

  • (A) int *f(void){ int x = 1; return &x; }
  • (B) int *f(void){ static int x = 1; return &x; }
  • (C) int *f(void){ int *p = malloc(4); free(p); return p; }
  • (D) int *f(void){ int a[3] = {1}; return a; }

Q3MCQ1 markLeak

Which line causes a memory leak (p was set by malloc and not yet freed)?

  • (A) free(p);
  • (B) p[0] = 1;
  • (C) p = NULL;
  • (D) q = p; free(q);

Q4MCQ2 marksOutput

What does this print?

int *c = calloc(4, sizeof(int));
int *m = malloc(2 * sizeof(int));
m[0] = 7; m[1] = 8;
m = realloc(m, 4 * sizeof(int));
m[2] = 9; m[3] = 10;
printf("%d %d %d %d | %d %d %d %d\n", c[0], c[1], c[2], c[3], m[0], m[1], m[2], m[3]);
free(c);
free(m);
  • (A) 0 0 0 0 | 7 8 9 10
  • (B) 0 0 0 0 | 7 8 0 0
  • (C) garbage | 7 8 9 10
  • (D) 0 0 0 0 | 9 10 7 8

Q5MSQ1 markHeap

Which statements are true?

  • (A) free(p) sets p to NULL.
  • (B) malloc returns NULL when it cannot allocate.
  • (C) realloc may return a different address.
  • (D) Heap memory lives until it is freed.

11 · Rule Card

  • Regions: code, static data, heap (malloc), stack (frames).
  • malloc(n) garbage; calloc(k, s) zeroed; realloc(p, n) may move; free(p).
  • Use n * sizeof(T); check NULL; use realloc’s result.
  • Heap lives until free; stack locals die on return.
  • Dangling: using freed/popped memory. Leak: losing the last pointer. Double free: freeing twice. All undefined or wasteful.
  • After free(p), set p = NULL.

12 · Concept Ledger

Unlocked in this lesson. From here on, these terms may be used.

heapmalloccallocreallocfreevoid * from mallocdangling pointermemory leakdouble freestack vs heap

13 · Answer Vault

Answer Vault

Try the questions first. Open when you are ready to check.

Recall Warm-up

  • (*p).x: the member x of the struct p points to.
  • B + (i·C + j)·w.
  • Dereferencing NULL is undefined behavior.

Self-Test

Q1 Answer: (A)1 mark

calloc zero-fills k × size bytes.

  • (B) is wrong: calloc zeroes the memory.
  • (C) is wrong: They are zero.
  • (D) is wrong: It reserves 5 ints, 20 bytes.

Re-read: Lesson 1.7 — Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Q2 Answer: (B)2 marks

A static lives for the whole run.

  • (A) is wrong: Local in a popped frame.
  • (C) is wrong: Freed before returning.
  • (D) is wrong: The local array dies with the frame.

Re-read: Lesson 1.7 — Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Q3 Answer: (C)1 mark

The last pointer to the block is lost without free.

  • (A) is wrong: That releases the block.
  • (B) is wrong: Ordinary use.
  • (D) is wrong: The block is freed through q.

Re-read: Lesson 1.7 — Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Q4 Answer: (A)2 marks

calloc zeroes; realloc keeps 7, 8 and the new cells are then set to 9, 10.

Output

0 0 0 0 | 7 8 9 10
  • (B) is wrong: m[2] and m[3] are assigned after realloc.
  • (C) is wrong: calloc zeroes its block.
  • (D) is wrong: realloc preserves order.

Re-read: Lesson 1.7 — Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Q5 Answer: (B) (C) (D)1 mark

free leaves p unchanged (dangling).

  • (A) is wrong: p keeps the old address.

Re-read: Lesson 1.7 — Dynamic memory: malloc, calloc, realloc, free; stack vs heap; dangling pointers, memory leaks, double free

Ready for the next idea?

Mark this item complete when you’ve finished reading and working through it.