c / c ++在堆栈上分配

时间:2013-11-01 11:06:45

标签: c++ c cpu-registers

我正在阅读[1]关于堆栈指针以及需要知道ebp(函数的堆栈的开始)和esp(end)。文章说你需要知道两者,因为堆栈可以增长,但我不知道在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

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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

这个指针可以指向免费存储,你可以动态地为它分配内存 - 而不必事先知道大小。此外,将堆栈帧保持为空是一个好主意,编译器甚至会用(可调)限制“强制”执行此操作。如果我没记错的话,MSVC有1MB。

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