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.
calloc()
? – Demavendcalloc
break any program that works fine withmalloc
? Everyone who usesmalloc
should be aware that he cannot rely on the content of the buffer. If it happens to be all zeroes that is just one possible result of random content. – NatalyanatanielC
tag because the question is aboutC
functions. I'm well aware of C++ memory management best practices, but there's one case when I feelmalloc
is the best way to allocate memory: when I need to allocate a buffer of a fixed size that's encapsulated in one of my classes. – Patronmalloc
. I'll just use::operator new
if I really have to. – Ponytailstd::unique_ptr<T[]>
is the way I would go. Now you have built in memory management. – Julietajuliettastd::unique_ptr
just binds that deletion to the pointers scope so you do not have to remember about it. astd::unique_ptr
with a default deleter should be just as efficient as doing it yourself with the benefit of not really being able to get it wrong. – Julietajuliettaclass unique_ptr {T* _ptr};
– Patronp = make_unique<...>(...);
needs to perform a null check onp
first, even if you statically know already that it is null. Moreover, passing unique pointers across function calls in inferior on the Itanium ABI, because the object has to go on the stack, while a raw pointer is passed in a register. (That's an implementation mistake, not a design mistake, but still.) – Bertledelete[]
then that doesn't even make the size of the pointer bigger. In gccsizeof(std::unique_ptr<int[]>)
is8
which is the same size as a single pointer(64 bit). – Julietajulietta