C/C++ 在堆栈上分配

c/c++ allocate on stack

本文关键字:分配 堆栈 C++      更新时间:2023-10-16

我正在阅读[1]关于堆栈指针以及了解ebp(函数堆栈的开始)和esp(结束)的需求。文章说你需要知道两者,因为堆栈可以增长,但我看不出这在 c/c++ 中是如何实现的。(我不是在谈论另一个函数调用,因为在我看来,这将使堆栈增长,做一些事情,然后递归地弹出并在调用前返回状态)

我做了一些研究,只看到人们说new在堆上分配。但是指针将是一个局部变量,对吧?这在编译时是已知的,并在调用函数时保留在堆栈中。

我开始认为,也许通过循环,您有数量不受控制的局部变量

int a;
for (int i = 0; i < n; ++i)
  int b = i + 3;

但是不,这不会分配 n 次b,并且只保留 1 个 int,就像它为 a 一样。

所以......任何例子?

[1):http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames

您可以使用

stdlib 中的alloca函数在堆栈上分配内存。我不建议在生产代码中使用此功能。很容易损坏堆栈或堆栈溢出。

使用 EBP 更多是为了方便。可以只使用 ESP。问题是,当函数的参数被推送到堆栈上时,所有变量和参数相对于 ESP 的地址都会发生变化。

通过将 EBP 设置为堆栈上的固定已知位置(通常在函数参数和局部变量之间),所有这些元素的地址在函数的整个生命周期内相对于 EBP 保持不变。它还可以帮助调试,因为函数末尾的 ESP 值应等于 EBP 的值。

据我所知,在编译时以不确定的方式增长堆栈的唯一方法是反复使用 alloca。

指针确实在堆栈上分配。在 32 位和 64 位架构上,大小通常分别为 4 或 8 字节。因此,您在编译时静态地知道指针的大小,并且如果您选择这样做,您可以将它们保留在堆栈上。

此指针可以指向空闲存储,您可以动态为其分配内存 - 而无需事先知道大小。此外,保持堆栈帧为空通常是一个好主意,编译器甚至会通过(可调)限制来"强制执行"这一点。如果我没记错的话,MSVC 有 1MB。

所以不,你不可能创建一个在编译时未知大小的堆栈帧。您发布的代码的堆栈帧将有 3 个整数(a、b、i)的空间。(可能还有一些填充、阴影空间等,不相关。(从技术上讲,在运行时扩展堆栈帧的大小是可能的,但您只是不想几乎永远这样做。