Skip to content

/compare/c/malloc-vs-calloc

malloc vs calloc in C: zeroed memory and overflow checks

The commands on this page have not been executed by our verification runner yet.updated
tool
C
compares
malloc(n * size) vs calloc(n, size)

malloc(size) allocates size bytes and leaves their contents indeterminate (whatever was there before). calloc(n, size) allocates an array of n elements of size bytes each and sets every byte to zero; it also fails with NULL if n * size would overflow, while malloc(n * size) silently allocates a wrong, smaller size when the multiplication overflows. Use calloc when you need zeroed memory or are allocating an array from a count; use malloc when you will overwrite every byte anyway.

Differences

malloccalloc
Signaturevoid *malloc(size_t size)void *calloc(size_t nmemb, size_t size)
ContentsIndeterminate (not initialized)All bits zero
n * size overflowYour multiplication wraps around: too small a bufferDetected: returns NULL
CostAllocation onlyAllocation plus zeroing (often free for fresh pages from the OS)
FailureReturns NULLReturns NULL
Releasefree()free()

Example

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

int main(void) {
    size_t n = 1000;

    int *a = malloc(n * sizeof *a);      /* contents undefined until written */
    int *b = calloc(n, sizeof *b);       /* every element is 0 */
    if (a == NULL || b == NULL) {
        perror("alloc");
        free(a); free(b);
        return 1;
    }
    for (size_t i = 0; i < n; i++) a[i] = (int)i;   /* malloc: initialize before reading */

    printf("%d %d\n", a[999], b[999]);   /* 999 0 */
    free(a);
    free(b);
    return 0;
}

Notes

  • All bits zero is 0 for integers and, on every common platform, 0.0 for IEEE 754 floating point and NULL for pointers, but the C standard does not guarantee the last two.
  • Reading memory from malloc before writing it is undefined behaviour; tools such as Valgrind (Conditional jump or move depends on uninitialised value) and MemorySanitizer report it.
  • To grow a buffer use realloc; newly added bytes are not zeroed. glibc also provides reallocarray(ptr, n, size) with the same overflow check as calloc.
  • sizeof *ptr instead of sizeof(int) keeps the size correct if the pointer type changes.

Sources