alloca() 在什么情况下有用?
当您始终可以在堆栈上分配足够大以适合所有用途的固定大小缓冲区时,为什么要使用 alloca() 呢?这不是一个反问句...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
当您始终可以在堆栈上分配足够大以适合所有用途的固定大小缓冲区时,为什么要使用 alloca() 呢?这不是一个反问句...
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(6)
如果缓冲区的大小在运行时变化,或者您只是有时需要它,那么它可能很有用:这将在每次调用中使用比固定大小缓冲区更少的堆栈空间。特别是当函数位于堆栈高层或递归时。
It could be useful if the size of the buffer varies at runtime, or if you only sometimes need it: this would use less stack space overall than a fixed-size buffer in each call. Particularly if the function is high up the stack or recursive.
当您无法使用
malloc()
(或 C++ 中的new
)时,使用alloca()
可能是合理的,或另一个内存分配器)可靠地,或者根本没有,但你可以假设你的堆栈上有更多的可用空间 - 也就是说,当你不能真正做任何其他事情时。例如,在 glibc 的 segfault.c,我们有:
Using
alloca()
may be reasonable when you are unable to usemalloc()
(ornew
in C++, or another memory allocator) reliably, or at all, but you can assume there's more space available on your stack - that is, when you can't really do anything else.For example, in
glibc
's segfault.c, we have:如果无法知道编译时可能需要的最大大小,您可能需要使用它。
您是否应该是另一个问题 -它不是标准的,也没有办法判断它是否会导致堆栈溢出。
You might want to use it if there's no way to know the maximum size you might need at compile time.
Whether you should is another question - it's not standard, and there's no way to tell whether it might cause a stack overflow.
我唯一一次看到 alloca 被使用是在 Open Dynamics Engine 中。
据我所知,他们用它分配了巨大的矩阵(因此编译后的程序可能需要 100MB 堆栈),当函数返回时,这些矩阵会自动释放(对我来说看起来像是智能指针的剽窃)。这是很久以前的事了。
尽管它可能比 new/malloc 快得多,但我仍然认为这是一个坏主意。
当场景变得过于复杂而无法处理时,程序可能会因堆栈溢出(即误导)而崩溃,而不是礼貌地耗尽 RAM。在我看来,这不是一个好的行为,特别是对于物理引擎来说,你可以很容易地期望有人向场景中扔几千块砖块,然后看看它们同时碰撞时会发生什么。另外,您必须手动设置堆栈大小 - 即在具有更多 RAM 的系统上,程序仍会受到堆栈大小的限制。
如果您需要固定大小的缓冲区供所有用途,那么您也可以将其放入静态/全局变量或使用堆内存。
The only time I ever saw alloca being used was in Open Dynamics Engine.
AFAIK they were allocating HUGE matrices with it (so compiled program could require 100MB stack), which were automatically freed when function returns (looks like smartpointer ripoff to me). This was quite a while ago.
Although it was probably much faster than new/malloc, I still think it was a bad idea.
Instead of politely running out of RAM program could crash with stack overflow (i.e. misleading) when scene became too complex to handle. Not a nice behavior, IMO, especially for physics engine, where you can easily expect someone to throw few thousands bricks into scene and see what happens when they all collide at once. Plus you had to set stack size manually - i.e. on system with more RAM, program would be still limited by stack size.
If you need fixed-size buffer for all uses, then you could as well put it into static/global variable or use heap memory.
实际上从来不需要
alloca()
函数;出于内存分配的目的,您可以在 C 中使用malloc()
/free()
(或 C++ 中的可能性集合之一),并达到几乎相同的实际效果。这样做的优点是可以更好地应对较小的堆栈大小。但是我已经看到[1]它的一种合法(如果黑客!)用途:用于检测 Windows 上潜在的堆栈溢出;如果分配(您想要访问的斜坡空间量)失败,您就会出局,但有足够的空间可以优雅地恢复。它被包装在
__try
/__ except
中,这样它就不会崩溃,并且需要额外的汇编技巧来避免 gcc 引起的麻烦。正如我所说,黑客。但这是我所见过的唯一有效的alloca()
用法。但不要这样做。最好编写不需要此类游戏的代码。
[1] 它是在 Tcl 8.4(也可能是 Tcl 的早期版本)中。在后来的版本中它被删除了。后来的版本删除了它,因为它很挑剔,非常棘手并且令人深感不安。 8.6 使用执行引擎的无堆栈实现,而不是那种时髦的方式。
The
alloca()
function is virtually never needed; for memory allocation purposes, you can usemalloc()
/free()
in C (or one of the collection of possibilities in C++) and achieve pretty much the same practical effect. This has the advantage of coping better with smaller stack sizes.However I have seen[1] one legit (if hacky!) use of it: for detecting potential stack overflow on Windows; if the allocation (of the amount of slop space you wanted to access) failed, you were out but had enough room to recover gracefully. It was wrapped in
__try
/__except
so that it didn't crash, and needed extra assembler tricks to avoid gcc-induced trouble. As I said, a hack. But a clever one that is the only valid use foralloca()
that I've ever seen.But don't do that. Better to write the code to not need such games.
[1] It was in Tcl 8.4 (and possibly earlier versions of Tcl). It was removed in later versions. Later versions removed it because it was finicky, very tricky and deeply troubling. 8.6 uses a stackless implementation of the execution engine instead of that sort of funkiness.
永远不会 - 它不是 C++ 的一部分,在 C 中没有用。但是,您不能分配“堆栈上的静态缓冲区” - 静态缓冲区是在编译时分配的,而不是在堆栈上分配的。
alloca() 的要点当然是它的大小不固定,它位于堆栈上,并且当函数退出时它会自动释放。 C++ 和 C 都有更好的机制来处理这个问题。
Never - it's not part of C++, and not useful in C. However, you cannot allocate "a static buffer on the stack" - static buffers are allocated at compile time, and not on the stack.
The point of alloca() is of course that it is not fixed sized, it is on the stack, and that it is freed automatically when a function exits. Both C++ and C have better mechanisms to handle this.