Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

C realloc, free and Memory Leaks

Memory from malloc and calloc stays reserved until the program gives it back with free. This topic shows how to change the size of a block, how to free memory correctly, and the mistakes to avoid.

realloc: change the size

realloc(pointer, newBytes) makes a block bigger or smaller and keeps its contents. It may move the block to another address, so always use the pointer it returns. If it fails it returns NULL and leaves the old block untouched, so store the result in a temporary pointer first.

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

int main(void) {
    int size = 3;
    int *a = malloc(size * sizeof(int));
    if (a == NULL) return 1;
    for (int i = 0; i < size; i++) a[i] = i + 1;

    int *bigger = realloc(a, 6 * sizeof(int));   // grow to 6 elements
    if (bigger == NULL) { free(a); return 1; }
    a = bigger;
    for (int i = size; i < 6; i++) a[i] = (i + 1) * 10;
    size = 6;

    for (int i = 0; i < size; i++) printf("%d ", a[i]);
    printf("\n");
    free(a);
    return 0;
}
Output
1 2 3 40 50 60 

free and the rules around it

  • Every block from malloc, calloc or realloc must be freed exactly once.
  • After free(p), the memory no longer belongs to you. Using it is a dangling pointer bug. Set p = NULL after freeing to make such mistakes visible.
  • Freeing the same block twice (double free) or freeing something that did not come from malloc can crash the program.
  • free(NULL) is allowed and does nothing.

Memory leaks

A leak is memory that is never freed. In a short program the system cleans up at the end, but in programs that run for a long time, such as servers or games, leaks pile up until memory runs out. With Safe mode on, our editor reports blocks that were never freed when the program ends. Try removing the free(a); line above with Safe mode on.

A linked list

Dynamic memory lets data structures grow one piece at a time. In a linked list, each node holds a value and a pointer to the next node:

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

typedef struct Node {
    int value;
    struct Node *next;
} Node;

Node *push(Node *head, int value) {
    Node *n = malloc(sizeof *n);
    if (n == NULL) return head;
    n->value = value;
    n->next = head;      // the new node goes in front
    return n;
}

int main(void) {
    Node *list = NULL;
    for (int v = 10; v <= 30; v += 10) {
        list = push(list, v);
    }
    for (Node *p = list; p != NULL; p = p->next) {
        printf("%d ", p->value);
    }
    printf("\n");
    while (list != NULL) {        // free every node
        Node *next = list->next;
        free(list);
        list = next;
    }
    return 0;
}
Output
30 20 10 

The freeing loop saves next before calling free, because after free(list) reading list->next would use freed memory.

Practice exercises

  1. Read numbers until the user types 0, storing them in memory that doubles its size with realloc whenever it is full. Print them at the end.
  2. Change the linked list so new nodes are added at the end instead of the front.
  3. Write a function that counts the nodes in a list.
  4. With Safe mode on, free a block twice and read the message.