Use calloc
for zero-filled allocations, but only when the zero-filling is really needed.
You should always use calloc(count,size)
instead of buff=malloc(total_size); memset(buff,0,total_size)
.
The call to zero-memset
is the key. Both malloc
and calloc
are translated into OS calls which do lots of optimizations, use hardware tricks whenever possible, etc. But there is little that OS can do with memset
.
On the other hand, when do you need to zero-fill the allocated memory? The only common use is for zero-ended arbitrary length elements, such as C-strings. If that's the case, sure, go with calloc
.
But if you allocate the structures in which the elements are either fixed-length or carry the length of arbitrary-sized elements with them (such as C++ strings and vectors), zero-filling is not helpful at all, and if you try to rely on it, it can lead to tricky bugs.
Suppose you write your custom linked list, and decide to skip the zeroing of the pointer to the next node by allocating the memory for the node with calloc
. It works fine, then someone uses it with custom placement new, which doesn't zero-fill. Trouble is, sometimes it will be zero-filled, and can pass all the usual testing, go in production, and there it will crash, crash sometimes, the dreaded unrepeatable bug.
For debug purposes, zero-filling is usually not that good, either. 0 is too common, you rarely can write something like assert(size);
because it's usually a valid value, too, you handle it with if(!size)
, not with asserts. On the debugger it won't catch your eye, either, there are usually zeros everywhere in your memory. The best practice is to avoid unsigned types for the lengths (signed lengths can be useful for runtime error handling and some of the most common overflow checks, too). So, while buff=malloc(total_size); memset(buff,0,total_size)
is to be avoided, the following is OK:
const signed char UNINIT_MEM=MY_SENTINEL_VALUE;
buff=malloc(total_size);
#if DEBUG_MEMORY
memset(buff,UNINIT_MEM,total_size);
#endif
In debug mode, runtime library or even OS do this for you sometimes, for example check this excellent post on VC++-specific sentinel values.