How does malloc() work and should you cast its return value in C?
malloc(size_t size) allocates size bytes of uninitialized memory on the heap and returns a void * pointer to the beginning of the block. Returns NULL if allocation fails.
The casting debate:
In C: Casting is not required and many style guides discourage it. void * implicitly converts to any pointer type in C. Casting can:
- Hide the bug of forgetting to
#include <stdlib.h>(in C89, missing prototype defaults to returning int) - Add visual clutter
- Cause maintenance issues if the type changes
In C++: Casting is required because C++ does not allow implicit conversion from void *.
Best practices:
- Always check the return value for NULL
- Use
sizeof(*p)instead ofsizeof(Type)to avoid type mismatches - Free the memory when done
Under the hood: malloc typically uses brk()/sbrk() for small allocations and mmap() for large ones. The allocator maintains metadata (size, free-list pointers) adjacent to each block.
1. Call malloc(num_bytes) -- returns void* or NULL
2. Check for NULL (allocation failure)
3. Use the memory
4. Call free(ptr) when done
Preferred pattern:
int *p = malloc(sizeof(*p) * count);
if (!p) { handle_error(); }
/* use p */
free(p);
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* Preferred C style: no cast, sizeof(*p) */
int *arr = malloc(sizeof(*arr) * 5);
if (arr == NULL) {
perror("malloc failed");
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = (i + 1) * 10;
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); /* 10 20 30 40 50 */
}
printf("\n");
free(arr);
arr = NULL; /* prevent dangling pointer */
/* Single element allocation */
double *val = malloc(sizeof(*val));
if (val) {
*val = 3.14;
printf("%.2f\n", *val); /* 3.14 */
free(val);
}
return 0;
}
- •malloc returns void* -- no cast needed in C (implicit conversion)
- •Always check for NULL return (allocation failure)
- •Use sizeof(*p) instead of sizeof(Type) for type-safe allocation
- •Memory is uninitialized -- contains garbage values
- •Every malloc must have a corresponding free
- •In C89, forgetting #include <stdlib.h> with a cast hides the implicit-int-return bug
- •malloc(0) is implementation-defined: may return NULL or a unique pointer that must not be dereferenced
- •Memory from malloc is NOT zero-initialized -- use calloc if you need zeroed memory
- •On Linux, malloc may succeed even without enough physical memory (overcommit) -- OOM killer handles it later