I am working with legacy C++ code that reserves a block of memory using malloc and divides it up into parts that are freed separately. Something like this:
const int N_floats_per_buffer = 100;
const int N_buffers = 2;
//reserve buffers en bloque
float * buffer = (float*) malloc(N_float_per_buffer * N_buffers * sizeof(float));
//then this block memory is divided into sub-blocks
float * sub_buffer[N_buffers];
for(int j = 0; j < N_buffers; ++j)
{
sub_buffer[j] = buffer + j*N_floats_per_buffer;
}
//do something with the buffers...
//...
//finally: memory is freed for the individual buffers
for(int j = 0; j < N_buffers; ++j)
{
if(sub_buffer[i]!=NULL) free(sub_buffer[j]);
}
It is actually even more confusing in the real code but I think I have captured the essence of it.
My question is: is that a memory leak?
It is not a memory leak. It is worse, undefined behavior.
You can only call free
on a pointer returned from malloc
(or calloc
, etc.). You are not allowed to call free
on a pointer pointing somewhere else in the returned storage block. Doing that causes undefined behavior.
Also on a more pedantic side, malloc
does not create any objects and pointer arithmetic requires the pointer to point to an element of an array object for it to have well-defined behavior in C++. Therefore you technically already have undefined behavior when you do
buffer + j*N_floats_per_buffer
although probably all compilers behave as expected (even though the standard made no guarantees). This was only resolved recently for C++20, where the required array will be created implicitly.
One should almost always only use new
/delete
, not malloc
/free
in C++.