2

我正在阅读有关堆栈指针的 [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

4

3 回答 3

5

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

于 2013-11-01T11:18:34.510 回答
1

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

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

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

于 2013-11-01T11:17:15.763 回答
0

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

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

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

于 2013-11-01T11:14:05.353 回答