SegFault

How much memory is required for malloc(0) ?

Why doing nothing is inefficient.

Jan 30 , 2021

At first glance, the answer seems clear: A request to allocate no memory should not require any memory at all. However, it is easily possible to exhaust all available memory without ever allocating more than zero bytes. But before we take a look at malloc(0) lets first check the simpler case of malloc(1).

People new to C/C++ often ask a similar question:

How can I get the size of a memory block a pointer points to ?

A common answer to this question is, that it's not possible. However, when we call free at a pointer, the standard library nows how much memory was allocated and frees it correctly. Most libraries do so by storing a small header directly preceeding the returned pointer. In the case of dlmalloc this structure consists of a variable of type size_t, which contains the memory blocks size and some flags. In addition to the size of this current block, it also stores the size of the block directly in front of it.

In case a block is not in use dlmalloc also stores pointers to the previous free block as well as the next free block. If we take this into consideration, we end up with a minimum block size of 32 bytes. This means that malloc(1) in reality allocates 32 bytes of memory. The following program allocates a byte and then outputs the size of the block, which unsurprisingly is 32 (or more).

#include <iostream>
#include <cstdlib>
int main() {
    size_t* ptr = (size_t*)malloc(1);
    std::cout << (ptr[-1] & ~0x1) << std::endl;
}

Now that we took a look at the simple case, we can take a look at malloc(0). If we read the C standard it might be surprising to find out that malloc is allowed to return a NULL pointer if the size is zero. However, since most programs treat it as an error if malloc returns NULL, most C libraries will instead return a valid memory block of minimum size, which as we found out is 32 bytes. The correct way to check for errors after malloc would be the following:

void* ptr = malloc(size);
if(ptr == NULL && size != 0) { /* Error */ }

So the answer to this question is: "It requires 32 bytes of memory to allocate no memory."