views:

3083

answers:

11

Alloca allocates memory from Stack rather then heap which is case in malloc. So, when I return from the routine the memory is freed. So, actually this solves my problem of freeing up of dynamically allocated memory . Freeing of memory allocated through malloc is a major headache and if somehow missed leads to all sorts memory problems.

So, my question is that in spite of the above features still alloca use is discouraged, why?

+15  A: 

The answer is right there in the man page (at least on Linux):

RETURN VALUE The alloca() function returns a pointer to the beginning of the allocated space. If the allocation causes stack overflow, program behaviour is undefined.

Which isn't to say it should never be used. One of the OSS projects I work on uses it extensively, and as long as you're not abusing it (alloca'ing huge values), it's fine. Once you go past the "few hundred bytes" mark, it's time to use malloc and friends, instead. You may still get allocation failures, but at least you'll have some indication of the failure instead of just blowing out the stack.

Sean Bright
So there's really no problem with it that you wouldn't also have with declaring large arrays?
T.E.D.
@sean I understand this, if I allocate too much memory ( as stack space is limited as compared to heap) this would lead to overflow; but same is the case with a local array as well. If I remain within my limits then I should be fine, right? Then also I still see anti alloa comments.
Vaibhav
Yes, if you remain within your limits, your code can assume a certain stack size, and the stack above your function's frame is consistently the same size, you should be fine.
Sean Bright
Not the same as large arrays, since the OS will guarentee space for those... they're statically sized.
singpolyma
@singpolyma - The following crashes for me, so I'm not sure what you mean: int main(int argc, char **argv) { char byebye[1024 * 1024 * 10]; /* 10MB array */; byebye[0] = 0; return 0; }
Sean Bright
@Sean: Yes, stack overflow risk is the reason given, but that reason is a bit silly. Firstly because (as Vaibhav says) large local arrays cause exactly the same problem, but are not nearly as vilified. Also, recursion can just as easily blow the stack. Sorry but I'm -1ing you to hopefully counter the prevailing idea that the reason given in the man page is justified.
j_random_hacker
I'm not entirely sure what point you are making... Don't use large local arrays? Functions that fail with undefined behavior should be used frequently and in earnest? Documentation cannot be trusted?
Sean Bright
My point is that the justification given in the man page makes no sense, since alloca() is exactly as "bad" as those other things (local arrays or recursive functions) that are considered kosher.
j_random_hacker
I think the warning in man page does make sense. There is no reason alloca couldn't work some magic to resize the stack to accommodate the allocation, so it's worth pointing out that any such magic is be implementation dependent, and is not required by the standard.
Charles E. Grant
s/go passed/go past/
Peter G.
@j_random_hacker: do you really think large local arrays are considered kosher?
ninjalj
@ninjalj: Not by highly experienced C/C++ programmers, but I do think many people who fear `alloca()` do not have the same fear of local arrays or recursion (in fact many people who will shout down `alloca()` will praise recursion because it "looks elegant"). I agree with Shaun's advice ("alloca() is fine for small allocations") but I disagree with the mindset that frames alloca() as uniquely evil among the 3 -- they are equally dangerous!
j_random_hacker
+2  A: 

Processes only have a limited amount of stack space available - far less than the amount of memory available to malloc().

By using alloca() you dramatically increase your chances of getting a Stack Overflow error (if you're lucky, or an inexplicable crash if you're not).

RichieHindle
+9  A: 

I found this link, which also has a very useful explanation of why using alloca can be difficult and dangerous.

FreeMemory
One thing I saw mentioned on that link which is not elsewhere on this page is that a function that uses `alloca()` requires separate registers for holding the stack pointer and frame pointer. On x86 CPUs >= 386, the stack pointer `ESP` can be used for both, freeing up `EBP` -- unless `alloca()` is used.
j_random_hacker
Another good point on that page is that unless the compiler's code generator handles it as a special case, `f(42, alloca(10), 43);` could crash due to possibility that the stack pointer is adjusted by `alloca()` *after* at least one of the arguments is pushed on it.
j_random_hacker
+5  A: 

All of the other answers are correct. However, if the thing you want to alloc using alloca() is reasonably small, I think that it's a good technique that's faster and more convenient than using malloc() or otherwise.

In other words, alloca( 0x00ffffff ) is dangerous and likely to cause overflow, exactly as much as char hugeArray[ 0x00ffffff ]; is. Be cautious and reasonable and you'll be fine.

JSBangs
+10  A: 

One issue is that it isn't standard, although it's widely supported. Other things being equal, I'd always use a standard function rather than a common compiler extension.

David Thornley
+1  A: 

Not very pretty, but if performance really matter, you could preallocate some space on the stack.

If you already now the max size of the memory block your need and you want to keep overflow checks, you could do something like :

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}
Sylvain
Is char array guaranteed to be correctly aligned for any data type? alloca provides such promise.
Juho Östman
+6  A: 
Arthur Ulfeldt
The VLA (variable length array) feature of C99 supports dynamically sized local variables without explicitly requiring alloca() to be used.
Jonathan Leffler
neato! found more info in section '3.4 Variable Length Array' of http://www.programmersheaven.com/2/Pointers-and-Arrays-page-2
Arthur Ulfeldt
A: 

for me alloca is more dangerous than malloc...

Arabcoder
+2  A: 

Here's why:

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

Not that anyone would write this code, but the size argument you're passing to alloca almost certainly comes from some sort of input, which could maliciously aim to get your program to alloca something huge like that. After all, if the size isn't based on input or doesn't have the possibility to be large, why didn't you just declare a small, fixed-size local buffer?

Virtually all code using alloca and/or C99 vlas has serious bugs which will lead to crashes (if you're lucky) or privilege compromise (if you're not so lucky).

R..
+2  A: 

Old question but nobody mentioned that it should be replaced by dynamic arrays.

char arr[size];

instead of

char *arr=alloca(size);

It's in the standard C99 and existed as compiler extension in many compilers.

tristopia
It's mentioned by Jonathan Leffler on a comment to Arthur Ulfeldt's answer.
ninjalj
Indeed, but it shows also how easy it is missed, as I hadn't seen it despite reading all responses before posting.
tristopia
+4  A: 

One of the most memorable bugs I had was to do with an inline function that used alloca. It manifested itself as a stack overflow (because it allocates on the stack) at random points of the program's execution.

In the header file:

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

In the implementation file:

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

So what happened was the compiler inlined DoSomething function and all the stack allocations were happening inside Process() function and thus blowing the stack up. In my defence (and I wasn't the one who found the issue, i had to go and cry to one of the senior developers when i couldn't fix it), it wasn't straight alloca, it was one of ATL string conversion macros.

So the lesson is - do not use alloca in functions that you think might be inlined.

Igor Zevaka
Interesting. But wouldn't that qualify as a compiler bug? After all, the inlining changed the behaviour of the code (it delayed the freeing of the space allocated using alloca).
sleske
Apparently, at least GCC will take this into account: "Note that certain usages in a function definition can make it unsuitable for inline substitution. Among these usages are: use of varargs, use of alloca, [...]". http://gcc.gnu.org/onlinedocs/gcc/Inline.html
sleske