Alloca()在堆栈上分配内存,而不是像malloc()那样在堆上分配内存。因此,当我从例程返回时,内存被释放。这实际上解决了动态分配内存的问题。通过malloc()释放分配的内存是一个非常令人头痛的问题,如果以某种方式错过释放会导致各种内存问题。
尽管有上述特性,为什么不鼓励使用alloca() ?
Alloca()在堆栈上分配内存,而不是像malloc()那样在堆上分配内存。因此,当我从例程返回时,内存被释放。这实际上解决了动态分配内存的问题。通过malloc()释放分配的内存是一个非常令人头痛的问题,如果以某种方式错过释放会导致各种内存问题。
尽管有上述特性,为什么不鼓励使用alloca() ?
当前回答
一个问题是,它不是标准的,尽管它得到了广泛的支持。在其他条件相同的情况下,我总是使用标准函数,而不是常用的编译器扩展。
其他回答
老问题了,但是没有人提到它应该被可变长度数组取代。
char arr[size];
而不是
char *arr=alloca(size);
它存在于标准C99中,并作为编译器扩展存在于许多编译器中。
实际上,alloca并不保证使用堆栈。 事实上,gcc-2.95的alloca实现使用malloc本身从堆中分配内存。此外,这个实现是有bug的,它可能会导致内存泄漏和一些意想不到的行为,如果你在一个块内调用它进一步使用goto。并不是说您永远都不应该使用它,但有时alloca会导致比它从me中释放更多的开销。
答案就在手册页中(至少在Linux上):
返回值 函数的作用是:返回一个指向对象开头的指针 分配空间。如果 分配的原因 堆栈溢出,程序行为未定义。
这并不是说它永远不应该被使用。我工作的一个OSS项目广泛使用它,只要你不滥用它(分配巨大的值),它是好的。一旦超过了“几百字节”的标记,就应该转而使用malloc和friends。您可能仍然会遇到分配失败,但至少您会得到一些失败的指示,而不是仅仅耗尽堆栈。
一个问题是,它不是标准的,尽管它得到了广泛的支持。在其他条件相同的情况下,我总是使用标准函数,而不是常用的编译器扩展。
alloca的一个缺陷是longjmp将它倒带。
也就是说,如果你用setjmp保存一个上下文,然后分配一些内存,然后longjmp到上下文,你可能会失去分配的内存。堆栈指针回到原来的位置,因此内存不再保留;如果你调用一个函数或执行另一个分配,你将破坏原来的分配。
为了澄清,我在这里特别提到的是一种情况,即longjmp不返回发生分配的函数!相反,函数使用setjmp保存上下文;然后使用alloca分配内存,最后在该上下文中执行longjmp。该函数的分配内存没有全部释放;就是从setjmp开始分配的所有内存。当然,我说的是观察到的行为;据我所知,任何分配都没有这样的要求。
The focus in the documentation is usually on the concept that alloca memory is associated with a function activation, not with any block; that multiple invocations of alloca just grab more stack memory which is all released when the function terminates. Not so; the memory is actually associated with the procedure context. When the context is restored with longjmp, so is the prior alloca state. It's a consequence of the stack pointer register itself being used for allocation, and also (necessarily) saved and restored in the jmp_buf.
顺便说一句,如果这样工作的话,这提供了一种合理的机制来故意释放使用alloca分配的内存。
我曾经遇到过这种情况,这是一个bug的根本原因。