Alloca()在堆栈上分配内存,而不是像malloc()那样在堆上分配内存。因此,当我从例程返回时,内存被释放。这实际上解决了动态分配内存的问题。通过malloc()释放分配的内存是一个非常令人头痛的问题,如果以某种方式错过释放会导致各种内存问题。
尽管有上述特性,为什么不鼓励使用alloca() ?
Alloca()在堆栈上分配内存,而不是像malloc()那样在堆上分配内存。因此,当我从例程返回时,内存被释放。这实际上解决了动态分配内存的问题。通过malloc()释放分配的内存是一个非常令人头痛的问题,如果以某种方式错过释放会导致各种内存问题。
尽管有上述特性,为什么不鼓励使用alloca() ?
当前回答
这个“老”问题有很多有趣的答案,甚至一些相对较新的答案,但我没有找到任何提到这个....
当正确和小心使用时,alloca()的一致使用 (可能是整个应用程序)来处理小的可变长度分配 (或C99 VLAs,如果可用)会导致整体堆栈降低 增长比使用超大的等效实现要快 固定长度的本地数组。因此,如果您仔细使用alloca(),它可能对您的堆栈有好处。
我在....上找到了这句话好吧,这句话是我编的。但真的,想想看....
@j_random_hacker在其他答案下面的评论中是非常正确的:避免使用alloca()来支持超大的本地数组并不能使你的程序更安全,免受堆栈溢出(除非你的编译器足够老,允许使用alloca()的函数内联,在这种情况下你应该升级,或者除非你在循环中使用alloca(),在这种情况下你应该……不要在循环内部使用alloca()。
I've worked on desktop/server environments and embedded systems. A lot of embedded systems don't use a heap at all (they don't even link in support for it), for reasons that include the perception that dynamically allocated memory is evil due to the risks of memory leaks on an application that never ever reboots for years at a time, or the more reasonable justification that dynamic memory is dangerous because it can't be known for certain that an application will never fragment its heap to the point of false memory exhaustion. So embedded programmers are left with few alternatives.
alloca()(或VLAs)可能是完成这项工作的合适工具。
I've seen time & time again where a programmer makes a stack-allocated buffer "big enough to handle any possible case". In a deeply nested call tree, repeated use of that (anti-?)pattern leads to exaggerated stack use. (Imagine a call tree 20 levels deep, where at each level for different reasons, the function blindly over-allocates a buffer of 1024 bytes "just to be safe" when generally it will only use 16 or less of them, and only in very rare cases may use more.) An alternative is to use alloca() or VLAs and allocate only as much stack space as your function needs, to avoid unnecessarily burdening the stack. Hopefully when one function in the call tree needs a larger-than-normal allocation, others in the call tree are still using their normal small allocations, and the overall application stack usage is significantly less than if every function blindly over-allocated a local buffer.
但是如果你选择使用alloca()…
根据本页上的其他答案,VLAs似乎应该是安全的(如果从循环中调用,它们不会复合堆栈分配),但如果您正在使用alloca(),请注意不要在循环中使用它,并确保您的函数不能内联,如果它有任何可能在另一个函数的循环中调用。
其他回答
一个问题是,它不是标准的,尽管它得到了广泛的支持。在其他条件相同的情况下,我总是使用标准函数,而不是常用的编译器扩展。
这个“老”问题有很多有趣的答案,甚至一些相对较新的答案,但我没有找到任何提到这个....
当正确和小心使用时,alloca()的一致使用 (可能是整个应用程序)来处理小的可变长度分配 (或C99 VLAs,如果可用)会导致整体堆栈降低 增长比使用超大的等效实现要快 固定长度的本地数组。因此,如果您仔细使用alloca(),它可能对您的堆栈有好处。
我在....上找到了这句话好吧,这句话是我编的。但真的,想想看....
@j_random_hacker在其他答案下面的评论中是非常正确的:避免使用alloca()来支持超大的本地数组并不能使你的程序更安全,免受堆栈溢出(除非你的编译器足够老,允许使用alloca()的函数内联,在这种情况下你应该升级,或者除非你在循环中使用alloca(),在这种情况下你应该……不要在循环内部使用alloca()。
I've worked on desktop/server environments and embedded systems. A lot of embedded systems don't use a heap at all (they don't even link in support for it), for reasons that include the perception that dynamically allocated memory is evil due to the risks of memory leaks on an application that never ever reboots for years at a time, or the more reasonable justification that dynamic memory is dangerous because it can't be known for certain that an application will never fragment its heap to the point of false memory exhaustion. So embedded programmers are left with few alternatives.
alloca()(或VLAs)可能是完成这项工作的合适工具。
I've seen time & time again where a programmer makes a stack-allocated buffer "big enough to handle any possible case". In a deeply nested call tree, repeated use of that (anti-?)pattern leads to exaggerated stack use. (Imagine a call tree 20 levels deep, where at each level for different reasons, the function blindly over-allocates a buffer of 1024 bytes "just to be safe" when generally it will only use 16 or less of them, and only in very rare cases may use more.) An alternative is to use alloca() or VLAs and allocate only as much stack space as your function needs, to avoid unnecessarily burdening the stack. Hopefully when one function in the call tree needs a larger-than-normal allocation, others in the call tree are still using their normal small allocations, and the overall application stack usage is significantly less than if every function blindly over-allocated a local buffer.
但是如果你选择使用alloca()…
根据本页上的其他答案,VLAs似乎应该是安全的(如果从循环中调用,它们不会复合堆栈分配),但如果您正在使用alloca(),请注意不要在循环中使用它,并确保您的函数不能内联,如果它有任何可能在另一个函数的循环中调用。
每个人都已经指出了堆栈溢出潜在的未定义行为,但我应该提到的是,Windows环境有一个很好的机制来捕捉这种情况,使用结构化异常(SEH)和保护页面。由于堆栈只在需要时增长,因此这些保护页驻留在未分配的区域。如果你对它们进行分配(通过溢出堆栈),就会抛出一个异常。
您可以捕获这个SEH异常并调用_resetstkoflw来重置堆栈并继续您的快乐之路。这并不理想,但这是另一种机制,至少可以在事情发生时知道哪里出了问题。*nix可能有类似的东西,但我不知道。
我建议通过包装alloca并在内部跟踪它来限制您的最大分配大小。如果你真的很认真,你可以在函数的顶部设置一些作用域哨兵来跟踪函数作用域中的任何分配,并检查它与项目允许的最大数量是否一致。
此外,除了不允许内存泄漏之外,alloca也不会导致内存碎片,这是非常重要的。我不认为alloca是不好的做法,如果你明智地使用它,这基本上适用于所有事情。: -)
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的根本原因。
为什么没有人提到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例子