Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C Language Dictionary
  3. malloc() / calloc() / realloc() / free()

malloc() / calloc() / realloc() / free()

Since: C89(1989)

Allocates memory as needed during program execution and releases it when done. Use these functions when you need to determine array sizes at runtime or work with large amounts of data. These functions are declared in <stdlib.h>.

Syntax

#include <stdlib.h>

// Allocates size bytes (uninitialized)
void *malloc(size_t size);

// Allocates num × size bytes, zero-initialized
void *calloc(size_t num, size_t size);

// Resizes allocated memory to new_size bytes
void *realloc(void *ptr, size_t new_size);

// Frees allocated memory
void free(void *ptr);

Dynamic Memory Functions

FunctionDescription
malloc(size)Allocates the specified number of bytes from the heap. The initial value is indeterminate. Returns NULL if allocation fails.
calloc(num, size)Allocates num elements of size bytes each and initializes all bytes to zero. Useful for initializing integer arrays.
realloc(ptr, new_size)Resizes the memory block pointed to by ptr to new_size bytes. If necessary, moves the block to a new location and copies the original contents.
free(ptr)Frees memory allocated by malloc, calloc, or realloc. Passing NULL is safe. Do not free a pointer that has already been freed.

Sample Code

Allocates an array with a runtime-determined size using malloc, creates a zero-initialized array with calloc, and expands an existing array with realloc.

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

int main(void) {
    int n;
    printf("Enter the number of elements: ");
    scanf("%d", &n);

    // malloc: allocate array with runtime-determined size
    int *arr = malloc(sizeof(int) * n);
    if (arr == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        arr[i] = (i + 1) * 10;
    }
    for (int i = 0; i < n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    free(arr);
    arr = NULL; // Prevent dangling pointer

    // calloc: all elements initialized to zero
    int *zeros = calloc(5, sizeof(int));
    for (int i = 0; i < 5; i++) {
        printf("%d ", zeros[i]);
    }
    printf("\n");
    free(zeros);

    // realloc: dynamically expand existing array
    int *buf = malloc(sizeof(int) * 3);
    buf[0] = 1; buf[1] = 2; buf[2] = 3;

    int *new_buf = realloc(buf, sizeof(int) * 6);
    if (new_buf == NULL) {
        free(buf);
        return 1;
    }
    buf = new_buf;
    buf[3] = 4; buf[4] = 5; buf[5] = 6;
    for (int i = 0; i < 6; i++) {
        printf("%d ", buf[i]);
    }
    printf("\n");
    free(buf);

    return 0;
}
gcc sample_malloc_free.c -o sample_malloc_free
./sample_malloc_free
Enter the number of elements: 3
arr[0] = 10
arr[1] = 20
arr[2] = 30
0 0 0 0 0
1 2 3 4 5 6

malloc / calloc / realloc Comparison

FunctionInitializationUse CaseBest Suited For
malloc(size)None (value is indeterminate)General-purpose allocation. Fast.When speed matters and you will write values immediately
calloc(num, size)All bytes set to zeroWhen zero-initialized storage is needed (integer arrays, flags)When you need zero-initialized memory
realloc(ptr, size)Extended portion is indeterminateResize an already-allocated blockDynamically growing or shrinking arrays

When you need a zero-initialized integer or flag array, using calloc() initializes all elements to zero. It is more explicit than malloc and saves you from writing a separate memset(0).

Preventing Memory Leaks

Failing to free allocated memory causes a memory leak, where memory usage grows continuously in long-running programs.

Assigning the return value of realloc directly back to the original pointer causes the original memory to be lost if realloc fails.

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

int *bad_grow(int *buf, int new_size) {
    buf = realloc(buf, sizeof(int) * new_size);
    return buf;
}

int main(void) {
    int *buf = malloc(sizeof(int) * 3);
    buf[0] = 10; buf[1] = 20; buf[2] = 30;

    buf = bad_grow(buf, 6);
    buf[3] = 40; buf[4] = 50; buf[5] = 60;

    for (int i = 0; i < 6; i++) {
        printf("%d ", buf[i]);
    }
    printf("\n");
    free(buf);
    return 0;
}

This works normally, but if realloc fails, the original memory is lost.

gcc realloc_ng.c -o realloc_ng
./realloc_ng
10 20 30 40 50 60

Use a temporary variable to check for NULL before reassigning. This ensures the original memory can be safely freed on failure.

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

int *good_grow(int *buf, int new_size) {
    int *tmp = realloc(buf, sizeof(int) * new_size);
    if (tmp == NULL) {
        free(buf);
        return NULL;
    }
    return tmp;
}

int main(void) {
    int *buf = malloc(sizeof(int) * 3);
    buf[0] = 10; buf[1] = 20; buf[2] = 30;

    buf = good_grow(buf, 6);
    if (buf == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return 1;
    }
    buf[3] = 40; buf[4] = 50; buf[5] = 60;

    for (int i = 0; i < 6; i++) {
        printf("%d ", buf[i]);
    }
    printf("\n");
    free(buf);
    return 0;
}
gcc realloc_ok.c -o realloc_ok
./realloc_ok
10 20 30 40 50 60

Even in functions with early returns, always call free on every return path.

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

int process(int trigger_error) {
    int *data = malloc(sizeof(int) * 100);
    if (data == NULL) { return -1; }

    if (trigger_error) {
        free(data);
        return -1;
    }

    data[0] = 42;
    printf("data[0] = %d\n", data[0]);
    free(data);
    data = NULL;
    return 0;
}

int main(void) {
    printf("Normal: %d\n", process(0));
    printf("Error: %d\n", process(1));
    return 0;
}
gcc early_return.c -o early_return
./early_return
data[0] = 42
Normal: 0
Error: -1

Common mistake 1: skipping the NULL check

Accessing memory without checking if malloc returned NULL causes a crash when allocation fails.

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

int main(void) {
    int *arr = malloc(sizeof(int) * 1000000);
    arr[0] = 1;
    printf("%d\n", arr[0]);
    free(arr);
    return 0;
}

If malloc returns NULL (out of memory)

./null_check_ng
Segmentation fault (core dumped)
null_check_ok.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *arr = malloc(sizeof(int) * 1000000);
    if (arr == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return 1;
    }
    arr[0] = 1;
    printf("%d\n", arr[0]);
    free(arr);
    return 0;
}
gcc null_check_ok.c -o null_check_ok
./null_check_ok
1

Common mistake 2: double free

Freeing the same pointer twice causes undefined behavior. Assign NULL after freeing to prevent this.

double_free_ng.c
#include <stdlib.h>

int main(void) {
    int *arr = malloc(sizeof(int) * 10);
    free(arr);
    free(arr);
    return 0;
}
gcc double_free_ng.c -o double_free_ng
./double_free_ng
free(): double free detected in tcache 2
Aborted (core dumped)
double_free_ok.c
#include <stdlib.h>

int main(void) {
    int *arr = malloc(sizeof(int) * 10);
    free(arr);
    arr = NULL;
    free(arr);
    return 0;
}
gcc double_free_ok.c -o double_free_ok
./double_free_ok

(normal exit, no output)

Common mistake 3: direct realloc assignment

Assigning the return value of realloc directly back to the original pointer causes a memory leak if realloc fails. Always use a temporary variable.

arr = realloc(arr, new_size);
int *tmp = realloc(arr, new_size);
if (tmp == NULL) { free(arr); return 1; }
arr = tmp;

Notes

Dynamically allocated memory is placed in a region called the "heap." Unlike automatic variables on the stack, heap memory is not released until you explicitly call free(). Failing to free allocated memory causes a "memory leak," where memory usage grows continuously over the lifetime of the program. Always free memory when you are done with it.

Using freed memory (a "dangling pointer") or freeing the same memory twice (a "double free") causes serious bugs. Always assign NULL to a pointer after freeing it.

When realloc() fails, it does not free the original pointer, so always check the return value with a separate variable before reassigning. For related functions, see also sizeof.

If you find any errors or copyright issues, please .