1

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?

5
  • One is dynamically-allocated, the other isn't. Commented Dec 16, 2013 at 3:34
  • "Designated initializer"? Where exactly do you see a designated initializer in these declarations? Commented Dec 16, 2013 at 3:43
  • Oops, I typed that out initially in both the question body and title then changed it in the question body. I forgot to update the title. Commented Dec 16, 2013 at 3:44
  • Are you asking what's happening under the hook in some specific implementation? Because you haven't said what implementation you're using. Are you asking what happens typically? Or what's required to happen? Commented Dec 16, 2013 at 3:45
  • I think the question was answered sufficiently, but I'm using Objective-C (and c) on iOS. Commented Dec 16, 2013 at 3:52

5 Answers 5

3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

4 Comments

Does this mean if rgba is created using an initializer, the memory will be freed automatically after it goes out of scope (suppose I defined it in a function, and it's not static, after the function is done, rgba will be freed automatically)?
@user3100783 Yes, the memory will be cleared automatically as soon as rgba is out of scope. That's the reason why it is not allowed to return pointers to such arrays from a function.
@user3100783 In both cases, rgba itself is freed automatically after it goes out of scope. The difference is that in one case rgba is a pointer and in the other it's an array. In the case where rgba is a pointer, something needs to free the array that it points to, and that array has no scope (other than the life of the program).
That's a good point @DavidSchwartz I didn't even think about the pointer being freed.
0

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.

1 Comment

The problem is not just a double free, it's freeing memory to something other than the allocator that allocated it, which is frequently catastrophic even if it's the only free.
0

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.

Comments

0

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.

4 Comments

Why do people bother to use dynamic memory for arrays? What are the pros and cons?
@user3100783: Dynamic memory is not just for arrays. The primary reason to use dynamic memory is to obtain manual control over the lifetime of the object. Dynamic memory is allocated at the moment you allocate it and disappears at the moment you deallocate it. Thus, you can create objects that live as long as you want them to live. None of this is possible with static or automatic objects. The latter kinds are created and destroyed automatically without you having any say in it.
@user3100783: Also, dynamic memory allocation allows you to "manufacture" objects in run-time quantities. Other kinds of memory can only create objects in compile-time quantities (variable-length arrays are exception from that rule). Finally, dynamic memory usually can accommodate huge objects, which are too large for other memory types.
@user3100783 In addition to AndreyT's points, sometimes your object simply does not fit on the stack, because it's too large. In cases like that you are also forced to use dynamic memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.