gcc堆栈内存分配

时间:2014-10-17 22:29:45

标签: c gcc gdb

我对内存布局分配感到困惑 我们可以说:

int flag = 0;
char array[10];

在内存堆栈中,数组位于标志上方。

(gdb) x/x array : 0xbffff4bc
(gdb) x/x flag :  0xbffff4cc

然而,我们可以说我们颠倒了这些界限:

char array[10];
int flag = 0;

内存的分配仍然是相同的

(gdb) x/x array : 0xbffff4bc
(gdb) x/x flag :  0xbffff4cc

为什么作业没有改变?不应该第二个选项中的标志位于堆栈中的数组上方吗?那么为什么在我使用-fno-stack-protector标志进行编译时,内存被分配给堆栈中整数以上的数组? 这是正确与否? 我在gcc 4.7.2 Debian下运行我的代码

修改

我刚发现了一个同样问题的帖子memory-allocation-issue-buffer-overflow-attack 但是,在阅读第一个答案时,在评论中认为当使用-fno-stack-protector进行编译时应解决问题(按声明顺序依次分配内存)。但它在我的情况下不起作用。 有什么建议吗?

3 个答案:

答案 0 :(得分:3)

正如@AndreyT的评论所指出的那样,标准中没有要求编译器必须按照它们在源中出现的顺序在堆栈上布局局部变量,或者在任何情况下都是如此。特别的顺序。

您可以通过将它们放在结构中来强制它们按顺序排列,因为标准确实指定了结构的布局规则(C99 6.7.2.1第13段)。即便如此,如果需要,编译器可以在元素之间自由填充。

但无论哪种方式你的策略都是错误的,因为标准还说在数组范围之外写作会引发“Undefined Behaivour”,这意味着无法保证它会安全地更新你的标志。不同的体系结构和/或编译器可以以不同的方式响应,可能导致硬件触发的异常或其他致命条件。你不能依赖任何特定的行为。

答案 1 :(得分:2)

在对此问题进行更多测试和实验之后,一个不错的解决方法是使用-fstack-protector允许编译器将缓冲区放置在内存中的标志变量下面,以保护自己免受缓冲区溢出攻击。

char password_buffer[16];
int auth_flag = 0;

所以当你以这种方式运行时,

x/x password_buffer: 0xbffff4bc
x/x &auth_flag: 0xbffff4b8

这意味着password_bufferauth_flag

以下的内存

答案 2 :(得分:0)

这是很正常的(但不能保证,正如@harmic指出的那样)首先分配更大的部分,以避免内存碎片。