Why use calloc to initialize the allocated memory to zero?

Viewed 1082

We know that the heap is an area of demand-zero memory that begins immediately after the uninitialized data area and grows upward (toward higher addresses). By demand-zero, it means the first time the CPU touches a virtual page in heap area, the corresponding physical page will be all zeros.

If that is the case, then why there is a function calloc used to initialize the allocated memory to zero? Why do demand-zero pages need to be initialized zero again if they will be zero already when accessed?

5 Answers

Because after you've used the space and released it with free(), it might be allocated again. If you don't use calloc(), there's no guarantee that the memory will be zeroed on the second time it is used. (Calling free() does not zero the space.)

calloc does not necessarily have to initialize the memory to zero by itself. The description of calloc says that:

The space is initialized to all bits zero.

but it does not say that it is calloc that does this, just that the memory is initialized to zero by some mechanism. This is unlike malloc:

  1. The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

calloc guarantees that the memory is zeroed, and malloc does not. If the contents of the block are copy-on-write zero pages, then calloc may know not to zero it again and is faster than malloc + memset, as memset would not know that the memory was already zeroed (unless the compiler optimizes malloc + memset(..., 0, ...) to calloc); on the other hand if the block is reused, then calloc needs to zero it, even if the caller would not care about zeroing, therefore a malloc would be faster than calloc if no zeroing is needed, because then calloc would indeed do effectively malloc + memset

In short, it's more portable to set the memory to zero explicitly if that's what your application needs; and faster to leave it alone if it doesn't. You don't have to use calloc() to get zero'd memory -- you could just use malloc() and zero it yourself (e.g.,using memset). But calloc() will give you zero'd memory more quickly, if it can take advantage of a platform-specific feature to get it.

the 'heap' memory will contain what ever trash was in memory when your program was loaded, (just like the stack)

It is up to your application to zero memory. There are a few ways to do that.

  1. calloc()
  2. a loop in your code
  3. memset()

This is in part historical, and in part as a useful feature

We had heap with uninitialised memory (which was not zero), so more quick to get memory. Then this was discovered that this is a security problem, so much later, you get memory cleared to zero (and never memory set by other processes). Do not assume all systems will do it (especially on small embedded CPU, where CPU and bus access are expensive (time and power).

calloc is very handy, when you allocate arrays (as you see, the signature is done for arrays). Often on arrays, you want to initialize values to zero. A loop is very slow, and static had already the initialization to zero. We have two possibilities: initialized memory with calloc or uninitialised memory with malloc.

Note: malloc doesn't guarantee to give you all zeros: it could give you already allocated (from your process) and freed memory. Just now new memory given by kernel is zeroed (e.g. with brk/sbrk, which is sometime called by malloc/calloc, in case of lack of free memory in existing heap memory). These are two different allocation of memory.

Related