LearnFrenzy
Sign in Take a free test

C Programming interview · Set 8 of 12

Dynamic Memory Allocation in C

  • 6 follow-up questions
  • 4 key points
  • Code examples
Test yourself

Own every byte you allocate

Interviewers check that you know where data lives, how to allocate and resize safely, and how to prevent and find leaks, dangling pointers and overflows.

  • LayoutText, data, BSS, heap and stack.
  • Allocationmalloc, calloc, realloc and free.
  • SafetyLeaks, dangling pointers, overflows and tools.

Memory management is the heart of C — and the source of its most serious bugs. Interviewers for embedded, systems and product roles always ask how you allocate, resize and free memory safely, and how you find leaks and corruption.

1. What is the memory layout of a C program?

From low to high addresses, typically: the text segment (code, read-only), initialised data (globals and statics with values), BSS (uninitialised globals and statics, zeroed), the heap (grows up; malloc), and the stack (grows down; local variables and function frames). Knowing where a variable lives explains its lifetime.

int counter = 5;        // initialised data
int total;              // BSS (zero)

int main(void) {
    int local = 1;                       // stack
    int *arr = malloc(10 * sizeof *arr); // heap
    static int calls;                    // BSS, lives for the whole program
    free(arr);
    return 0;
}

2. malloc vs calloc vs realloc?

malloc(size) allocates uninitialised memory. calloc(n, size) allocates zeroed memory for n elements and checks the multiplication for overflow. realloc(ptr, size) resizes a block, possibly moving it; it returns NULL on failure and leaves the original block valid. All return void*, which converts to any object pointer in C without a cast.

int *scores = calloc(5, sizeof *scores);   // [0,0,0,0,0]
if (!scores) return -1;

int *bigger = realloc(scores, 10 * sizeof *bigger);
if (!bigger) {          // original block is still valid here
    free(scores);
    return -1;
}
scores = bigger;

3. Why must you check the return value of malloc?

Allocation can fail and return NULL (out of memory, or an absurd size from a bug). Dereferencing NULL is undefined behaviour — usually a crash. Always check, and handle the failure (clean up and report an error).


4. What is a memory leak and how do you prevent it?

Memory allocated and never freed, typically because the last pointer to it was overwritten or a function returned early. Long-running programs eventually run out of memory. Prevent it with clear ownership rules (who frees what), a single cleanup path (goto cleanup is idiomatic in C), and tools such as Valgrind or AddressSanitizer.

int process(const char *path) {
    int rc = -1;
    char *buf = NULL;
    FILE *f = fopen(path, "r");
    if (!f) goto cleanup;
    buf = malloc(4096);
    if (!buf) goto cleanup;
    /* ... use f and buf ... */
    rc = 0;
cleanup:
    free(buf);              // free(NULL) is safe
    if (f) fclose(f);
    return rc;
}

5. What are dangling pointers and double free?

A dangling pointer still points to memory that has been freed (or to a local variable that went out of scope); using it is undefined behaviour. A double free frees the same block twice and can corrupt the allocator. Set pointers to NULL after freeing and never return the address of a local variable.

char *make_name(void) {
    char name[] = "Asha";
    return name;            // BUG: dangling — name dies when the function returns
}

char *make_name_ok(void) {
    char *name = malloc(5);
    if (name) strcpy(name, "Asha");
    return name;            // caller must free
}

free(p);
p = NULL;                   // prevents accidental reuse / double free

6. How do you allocate a 2D array dynamically?

Either an array of row pointers (flexible, each row allocated separately) or one contiguous block indexed manually (faster, one allocation, one free). The contiguous version is usually better.

int rows = 3, cols = 4;
int *grid = malloc((size_t)rows * cols * sizeof *grid);   // one block
if (!grid) return -1;
for (int r = 0; r < rows; r++)
    for (int c = 0; c < cols; c++)
        grid[r * cols + c] = r + c;
free(grid);

7. What is a buffer overflow and how do you avoid it?

Writing past the end of an array — the classic cause of crashes and security holes. Avoid gets (removed from C11) and unbounded strcpy/sprintf; use fgets, snprintf and explicit length checks, and compile with warnings and sanitizers.

char name[16];
if (fgets(name, sizeof name, stdin)) {
    name[strcspn(name, "\n")] = '\0';      // strip newline
}
char msg[64];
snprintf(msg, sizeof msg, "Hello, %s!", name);   // never overflows msg

8. How do you find memory bugs?

Compile with warnings (-Wall -Wextra) and run tests under AddressSanitizer (-fsanitize=address), which catches overflows, use-after-free and leaks with exact line numbers, or under Valgrind. Static analysers (clang-tidy, cppcheck) catch more before running.

gcc -g -Wall -Wextra -fsanitize=address,undefined app.c -o app && ./app
valgrind --leak-check=full ./app

Remember

Key points

  • Check every allocation

    malloc can return NULL.

  • realloc into a temporary

    Do not lose the original on failure.

  • NULL after free

    Prevents use-after-free and double free.

  • Use sanitizers

    ASan and Valgrind find bugs fast.

Interview drill

Follow-up questions

What the interviewer asks after your first answer. Turn on practice mode, answer each one aloud, then reveal.

  1. 1 What does free(NULL) do? Basic

    Nothing — it is defined to be safe, which simplifies cleanup code.

  2. 2 Does free() return memory to the operating system? Intermediate

    Usually not immediately; the allocator keeps it for future allocations. Large blocks may be returned (implementation-specific).

  3. 3 What is the difference between stack and heap allocation? Basic

    Stack memory is automatic, fast and freed when the function returns, but limited in size. Heap memory lives until freed, can be large and resized, but is slower and must be managed manually.

  4. 4 What is memory fragmentation? Advanced

    Free memory split into small non-contiguous pieces, so a large allocation fails despite enough total free memory. Pools and fixed-size allocators reduce it in embedded systems.

  5. 5 Why is sizeof *ptr preferred over sizeof(int) in malloc? Intermediate

    It stays correct if the pointer's type changes later, removing a common source of bugs.

  6. 6 What is a wild pointer? Basic

    An uninitialised pointer holding a garbage address. Always initialise pointers, to NULL if nothing else.

Preparing with friends?

Share this page with your study group or placement batch.

Search LearnFrenzy

Esc

Quick links