Learning path

Full curriculum

Full curriculum

Unit content

Dynamic memory allocation in C

Some objects must outlive the function call that created them, or have a size that is known only while the program is running. C provides dynamic allocation for this purpose.

malloc

malloc(n) requests a region large enough for n bytes and returns a pointer to suitably aligned storage, or a null pointer if the request cannot be satisfied.

int *values = malloc(count * sizeof *values);
if (values == NULL) {
    /* allocation failed */
}

The allocated storage does not initially contain meaningful values.

calloc

calloc(count, size) allocates storage for an array and initializes all bytes to zero. It also lets the allocation interface perform the multiplication needed for the total size.

free

An allocation remains alive until it is released with free or until the process terminates.

free(values);
values = NULL;

After free, pointers that referred to the allocation no longer designate a live object. Dereferencing them is a use-after-free error.

Calling free twice on the same allocation is also invalid.

realloc

realloc changes the size of an existing allocation. The allocator may extend it in place or move the data to another region and return a different pointer.

Because failure can leave the original allocation intact, code commonly saves the result in a temporary pointer before replacing the original one.

Ownership and lifetime

C does not automatically encode who owns dynamically allocated memory. Programs must establish conventions describing

  • who is responsible for calling free;
  • whether a pointer borrows or owns an allocation;
  • how long borrowed pointers remain valid.

Failing to release unreachable allocations produces memory leaks.

The heap as an abstraction

Dynamically allocated storage is often informally called the heap, but it should not be confused with the heap data structure. Nor does every malloc request correspond directly to an operating-system request: a user-space allocator normally manages larger regions obtained from the system and serves many individual allocations from them.

Dynamic allocation therefore introduces two different questions: how a C program uses allocated objects safely, and how an allocator implements the apparently simple allocation interface.