Does this code return an invalid reference to a variable allocated on the stack? Or what:
void *f(size_t sz) {
return alloca(sz);
}
Or is it a special case that is handled by the alloca implementation / compiler support like f(alloca(size), alloca(size))
would be?
alloca
allocates space in the stack frame of f
. You can't do anything useful with it once the function returns (it's not "reserved" anymore).
The alloca() function allocates size bytes of space in the stack frame
of the caller. This temporary space is automatically freed when the
function that called alloca() returns to its caller.
this:
void *f() {
char* pc4 = alloca(4);
...
}
is exactly this:
void *f() {
char pc4[4];
...
}
Neither you can return / use pc4 outside the function in second case nor you can do the same in first case.
Yes, the code returns an invalid pointer. alloca
call cannot be wrapped into a function. If you need to wrap alloca
, you are limited to macro wrappers.
As others have said, it'll be freed, and I don't really see how you could change the behavior. If you look at how an alloca
compiles on amd-64:
pushq %rbp
movq %rsp, %rbp
subq $144, %rsp
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
leave
ret
You see
1) Alloca isn't actually a function call (because, as you said, it would have to handle the stack differently!)
2) Whatever alloca does to the stack pointer is just going to get clobbered at the end of the function when rbp
overwrites rsp
So could you get the behavior you ask about (without writing assembly)? That's a tricky question, and I don't know, but it seems like probably not.
I have never used alloca myself but I read about "inline problem" here:
Why is the use of alloca() not considered good practice?
The answer "One of the most memorable bugs ..." is very interesting.
So it is not true that the memory will definitely be freed when the function goes out of scope.
As per the Linux manual page:
The alloca()
function allocates space in the stack frame of the
caller, and returns a pointer to the allocated block. This temporary
space is automatically freed when the function from which alloca()
is called returns.
That means, an attempt to access the memory returned by f()
will lead to undefined behavior as it is freed when f()
returns.