以下代码段有意访问 t[4]
之后的下一个 sizeof(int) 字节,因此我知道这里犯的错误。我这样做只是作为一个实验,看看编译器如何处理堆栈分配。
int t[5], i;
for (i = 0; i <= 5; i++) {
t[i] = 0;
}
当在 Windows 上使用 GNU C 编译器的移植版本执行此代码时,程序总是陷入无限循环。我确信这只会发生,因为 t
和 i
在堆栈上依次分配,并且 t[5]
指向到与 i
变量相同的地址。因此,当执行t[5] = 0
时,程序实际上将i
的值设置为零。
但是,当使用不同版本的 GNU C 编译器编译此文件时,我从未遇到无限循环。 t[5]
的地址与 i
的地址不同。
我的问题是,为什么会出现这种不同的行为?我知道您不应该对此结果做出任何假设,但是堆栈分配不应该以相同的方式发生吗?
我真正好奇的是编译器如何管理这些堆栈分配。有垫子吗?顺序是否始终与源代码中的顺序相同?显然这与 C 标准无关,并且实现之间存在差异,甚至同一编译器的不同版本也存在差异。我很好奇在这种特殊情况下可能的结果和考虑因素是什么。
最佳答案
您正在处理未定义的行为。编译器不需要按顺序布置自动变量(就像它们出现在源代码中一样)。其中一些可能位于寄存器中,或者它们可能以不同的方式排序,例如,较小的偏移量更便宜。
这样的要求仅适用于结构体的成员(成员之间具有任意填充)。
Is there any padding?
是的,编译器会遵守每种类型的对齐要求并相应地放置变量。
Is the order always the same as in the source code?
不,但这是许多漏洞利用所依赖的东西。缓冲区溢出可能会覆盖相邻的变量并危及整个程序的执行。
关于c - 关于C中栈分配的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35622441/