Alloca()在堆栈上分配内存,而不是像malloc()那样在堆上分配内存。因此,当我从例程返回时,内存被释放。这实际上解决了动态分配内存的问题。通过malloc()释放分配的内存是一个非常令人头痛的问题,如果以某种方式错过释放会导致各种内存问题。

尽管有上述特性,为什么不鼓励使用alloca() ?


当前回答

实际上,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的根本原因。

alloca() is very useful if you can't use a standard local variable because its size would need to be determined at runtime and you can absolutely guarantee that the pointer you get from alloca() will NEVER be used after this function returns. You can be fairly safe if you do not return the pointer, or anything that contains it. do not store the pointer in any structure allocated on the heap do not let any other thread use the pointer The real danger comes from the chance that someone else will violate these conditions sometime later. With that in mind it's great for passing buffers to functions that format text into them :)

为什么没有人提到GNU文档中介绍的这个例子?

https://www.gnu.org/software/libc/manual/html_node/Advantages-of-Alloca.html

使用longjmp自动完成的非本地退出(参见非本地退出) 方法退出时释放使用alloca分配的空间 调用alloca的函数。这是使用的最重要的原因 alloca

建议阅读顺序1->2->3->1:

https://www.gnu.org/software/libc/manual/html_node/Advantages-of-Alloca.html 来自非本地出口的介绍和详细信息 Alloca例子

alloca并不比变长数组(VLA)更糟糕,但它比在堆上分配更危险。

在x86上(最常见的是在ARM上),堆栈向下增长,这带来了一定的风险:如果你不小心写超出了用alloca分配的块(例如由于缓冲区溢出),那么你将覆盖你的函数的返回地址,因为它位于堆栈的“上面”,即在你分配的块之后。

这样做的后果是双重的:

程序将崩溃的壮观,它将不可能告诉为什么或哪里崩溃(堆栈将最有可能unwind到一个随机地址,由于覆盖的帧指针)。 它使缓冲区溢出的危险增加了许多倍,因为恶意用户可以制作一个特殊的有效负载,将其放在堆栈上,因此最终可以执行。

相反,如果你在堆上写超过一个块,你“只是”得到堆损坏。程序可能会意外终止,但会正确地展开堆栈,从而减少恶意代码执行的机会。