Implementing calloc
calloc: Allocate and Zero-Initialize
calloc is malloc with two differences:
- Takes
countandsizeseparately (for arrays) - 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 = 0x100000000andsize = 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)orcalloc(x, 0)returns NULL (or minimal allocation - we'll return NULL)
Run tests to see results
No issues detected