Pergunta

Why do I have to free an array created using malloc, but not one created using an initializer?

float* rgba = malloc(4 * sizeof(float));
free(rgba);

versus:

float rgba[] = { 0.0f, 0.0f, 0.0f, 0.0f };
free(rgba); // ERROR

What is happening under the hood here in the second one?

Foi útil?

Solução 2

The difference is that malloc always allocates memory from the dynamic memory, while initializer places the data in either the static or the automatic memory, depending on the context where you define rgba:

  • If your definition is outside any function, or if you add static to the definition, rgba is allocated in the static area, and gets either static or global visibility
  • If you declaration is inside a function, then the memory is allocated in the automatic area (also known as "on the stack").

Since calls of free may be passed only pointers returned by a function from the malloc family (malloc/calloc/realloc) or other functions that return dynamic memory (e.g. strdup), calling free on non-malloc-ed pointer is undefined behavior.

Outras dicas

In the first case:

there is allocation in the heap memory segment. Whatever allocated in the heap has to be de-allocated by the user. The compiler is not responsible for the automatic de-allocation.

In the second case :

The memory allocation takes place either in the stack or in the data segment depending on whether you allocate the array inside a function or globally!

If you allocate the array outside a function it gets allocated in the data segment section of memory.

if you allocate the array inside the function it gets allocated in the stack.

Whatever allocated in the stack or data segment automatically gets de-allocated. There is no need for explicit de-allocation from the user side.

Because

float rgba[] = { 0.0f, 0.0f, 0.0f, 0.0f };

here array memory is allocated on stack. Compiler itself frees that memory when program goes out of the scope. If you free it, compiler will free it and it will case of double free.

In the first, you are allocating the memory to heap. User is responsible for freeing the heap memory allocated by the user. That is why free in first case will work.

First case is dynamically allocated memory , where memory is allocated in heap section of memory. This means that the memory allocation is done at run-time, after compilation.

Second case is the normal, local variable creation, where memory is allocated during compile-time in the stack section of memory.

the free() function is used to de-allocate memory allocated during run time only, not compile time. Hence you are getting error.

Firstly, there are no "designated initializers" in any of your examples. Your second example uses aggregate initializer syntax without any actual initializers in it being "designated".

Secondly, none of this has anything to do much with aggregate initializers. The primary difference resides on the left-hand side: float* rgba in the first case and float rgba[] in the second case.

In the second case you are actually declaring an array, and it is either a local or static array (depending on where that declaration resides). Local and static memory shall not be deallocated with free. It cannot be deallocated by you at all. You don't own local or static memory, which means that it is not your business to worry about its deallocation. Local and static objects have pre-determined lifetimes that follow pre-determined rules. They are created and destroyed automatically in full accordance with those rules.

In the first case you are not really declaring an array at all. You are declaring a pointer that points to a dynamically allocated memory block. You own all memory blocks you dynamically allocate, which means it is your responsibility to properly deallocate them.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top