Reputation: 68770
Is it possible to free memory allocated by C's alloca() explicitly, before the current function exits? If so,how?
Upvotes: 9
Views: 7694
Reputation: 1
You don't need to write any custom freea(...)
kind of function, nor use VLA.
Memory allocated on the stack can be easily freed in both C and C++ (C++ doesn't support VLAs).
The alloca(...)
allocates on the stack, right? This means the memory is going to be deallocated when it goes out of scope... so just use scopes!
#include <alloca.h>
int main()
{
{
void* ptr = alloca(1024);
// do your stuff
} // memory is deallocated here
return 0;
}
As you can see from the godbolt online compiler, the assembly (with no optimization) does the right thing: https://godbolt.org/z/Gn5YMa
Upvotes: -1
Reputation: 301
Yes, but it depends on the implementation of alloca(). A reasonable and simple implementation of alloca() is that the newly allocated block placed on top of stack by adjusting the stack pointer. Therefore to free this memory we only need to do a negative allocation (but you need to study the real implementation of alloca()), let's verify it by taking the following non-portable code for example:
#include <stdio.h>
#include <alloca.h>
int main()
{
unsigned long p0, p1, p2;
p0=(unsigned long)alloca(0);
p1=(unsigned long)alloca((size_t) 0x1000);
p2=(unsigned long)alloca((size_t)-0x1000);
printf( "p0=%lX, p1=%lX, p2=%lX\n", p0, p1, p2 );
return 0;
}
On an old x64 machine with clang 2.9, a sample output is:
p0=7FFF2C75B89F, p1=7FFF2C75A89F, p2=7FFF2C75B89F
So we know the implementation does not validate the argument -0x1000, otherwise the unsigned value will be a very large integer. Stack pointer was originally 0x...B89F; since this stack grows upward alloca(0x1000) therefore change the stack pointer up to (0x...B89F - 0x1000) = 0x...A89F. After the negative allocation (0xA89F - (-0x1000)) the stack pointer went back to 0x...B89F.
However, with gcc 4.8.3, a sample output is:
p0=7FFFA3E27A90, p1=7FFFA3E26A80, p2=7FFFA3E27A70
In /usr/include/alloca.h we found:
#ifdef __GNUC__
# define alloca(size) __builtin_alloca (size)
#endif /* GCC. */
So we know that the builtin alloca function provided by gcc 4.8.3 did similar thing except it allocate extra 0x10 bytes as a safety margin. When doing negative allocation it still assumes it grows upward and therefore tried to reserve 0x10 extra bytes (- 0x10) so p2= 0x...6A80 - (-0x1000) - 0x10 = 0x...7A70. So, be extra careful.
Upvotes: 1
Reputation: 9402
Using C99 you can achieve the same thing using a Variable Length Array. Just declare the VLA in a new scope; it will automatically be freed when the scope exits.
For example:
int some_function(int n) {
// n has the desired length of the array
...
{ // new scope
int arr[n]; // instead of int *arr = alloca(n*sizeof(int));
// do stuff with array
}
// function continues with arr deallocated
...
}
Upvotes: 3
Reputation: 44807
This would be useful for continuation passing style (CPS), rather a realloca.
You could call a function which alloca'd and manipulated a string on the top of the stack, before shrinking the stack back down to the length of the string and calling the next function.
There's no conceptual reason why there couldn't be an freea(), which would be a nop for anything but the topmost entry on the stack.
Upvotes: 2
Reputation: 4307
It is possible, but there is no pre-written function to do it. You'd have to delve into your compiler's implementation of alloca() to figure out what it is doing, then write your own freea(). Since every compiler does alloca() differently, you'd have to rewrite your freea() for each compiler.
But I find it hard to believe this would be worth the trouble. Just use malloc/free if you need to explicitly free it - those functions are usually heavily optimized. Take advantage of them.
Upvotes: 9
Reputation: 176743
From http://www.gnu.org/software/libc/manual/html_mono/libc.html#Variable-Size-Automatic:
Allocating a block with
alloca
is an explicit action; you can allocate as many blocks as you wish, and compute the size at run time. But all the blocks are freed when you exit the function that alloca was called from, just as if they were automatic variables declared in that function. There is no way to free the space explicitly.
Upvotes: 13
Reputation: 19666
You are allocating on the stack with alloca(); If something else happened afterwards (and you can't control it without writing everything in assembly), you can't just shrink the stack back. So until you leave the stack frame of your function, this is impossible.
This is also why you can really mess things up if you overflow the allocated buffer. You can start overwriting addresses of code your function returns to, causing it to jump elsewhere, all kinds of horrid stuff. Be careful!
Malloc works on the heap, so that's why it is much more flexible in what it can do.
Upvotes: 2
Reputation: 882098
No, because it's allocated on the stack along with the local variables. If you want memory that you can explicitly free, use one of the dynamic memory allocation functions.
There's no hybrid that allows you to explicitly free AND have it automatically free on function exit as well, at least not in the standard.
Upvotes: 1