Implementing calloc

medium · memory, allocation, security

calloc: Allocate and Zero-Initialize

calloc is malloc with two differences:

  1. Takes count and size separately (for arrays)
  2. Zero-initializes the memory

Why calloc Exists

// malloc: returns uninitialized (garbage) memory
int *arr = malloc(100 * sizeof(int));
// arr[0] could be anything! Must initialize before use.

// calloc: returns zeroed memory
int *arr = calloc(100, sizeof(int));
// arr[0] == 0, arr[1] == 0, ... guaranteed!

Overflow Safety

The separate count/size parameters allow detecting overflow:

// Dangerous: might overflow silently
void *p = malloc(count * size);

// Safer: calloc can check for overflow
void *p = calloc(count, size);

For very large count * size, the multiplication might overflow and wrap around:

  • count = 0x100000000 and size = 2
  • On 32-bit: count * size = 0 (overflow wraps!)
  • malloc(0) returns NULL or small allocation - disaster!

Your Task

// Zero-fill n bytes of memory
void my_memset(void *ptr, int value, size_t n);

// Allocate count * size bytes, zero-initialized
// Returns NULL if allocation fails or on overflow
void *my_calloc(size_t count, size_t size);

Implementation

void *my_calloc(size_t count, size_t size) {
    // Check for overflow: if count * size would overflow
    if (count != 0 && size > SIZE_MAX / count) {
        return NULL;
    }

    size_t total = count * size;
    void *ptr = my_malloc(total);
    if (ptr == NULL) {
        return NULL;
    }

    my_memset(ptr, 0, total);
    return ptr;
}

Overflow Detection

The key check is:

if (count != 0 && size > SIZE_MAX / count)

This says: "if multiplying would exceed SIZE_MAX, fail."

Constraints

  • Must zero-initialize all bytes
  • Must handle overflow (return NULL)
  • calloc(0, x) or calloc(x, 0) returns NULL (or minimal allocation - we'll return NULL)
Run tests to see results
No issues detected