Pointers & Memory · intermediate · ~12 min

malloc and the heap

Allocate a checked-size array, initialize it, and transfer ownership to its caller.

Overview

malloc requests storage at runtime and returns a pointer to it. The key difference from an automatic local object is that allocated storage remains alive until it is released with free. Runtime sizing is useful, but it is not unique to malloc: variable-length automatic arrays exist in some C language modes and implementations.

Core concepts

Call malloc(count * sizeof *p) only after checking that the multiplication fits in size_t. Include <stdlib.h> for malloc and free. No cast is required for the returned void pointer in C.

A failed allocation returns NULL. Check it before reading or writing through the result. Successful allocation provides uninitialized bytes; assign each element before reading it.

Choose and document an owner. A function returning a fresh allocation usually transfers responsibility for freeing it to its caller. Returning the address of a local array cannot implement this contract: that object's lifetime ends when execution leaves its block.

Lesson

malloc requests storage at runtime and returns a pointer to it. The key difference from an automatic local object is that allocated storage remains alive until it is released with free. Runtime sizing is useful, but it is not unique to malloc: variable-length automatic arrays exist in some C language modes and implementations.

Code examples

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
    size_t n = 3;
    int *p = NULL;
    if (n > SIZE_MAX / sizeof *p) return 1;
    p = malloc(n * sizeof *p);
    if (p == NULL) return 1;
    for (size_t i = 0; i < n; ++i) p[i] = (int)i;
    printf("%d %d %d\n", p[0], p[1], p[2]);
    free(p);
    return 0;
}

Expected output on a successful allocation, where applicable:

0 1 2

Line by line

The size check precedes multiplication. The NULL check precedes all writes. Every printed element is initialized, and the single owner releases the block after its last use.

Practice tasks

  1. Identify the size, failure, initialization, and cleanup steps in the example.
  2. Complete Allocate a range.
  3. Solve Duplicate an array; prove the copy is independent by changing it.
  4. Continue to free and ownership before attempting a resizable buffer or arena allocator.

Summary

Check the size calculation, check the allocation result, initialize before reading, and name the owner. Allocated lifetime is explicit; automatic storage is not universally limited to compile-time sizes.

Practice with these exercises