2011-02-23 76 views
4

您好我有由海湾合作委员会(或g ++)对可能的堆栈优化问题..在FreeBSD下GCC堆栈优化

示例代码(做UNIX方差事吗?):

void main() { 
    char bing[100]; 
    .. 
    string buffer = ....; 
    .. 
} 

我发现了什么在gdb中该程序的核心转储是bing的地址 实际上低于该缓冲区(即,& bing [0] < &缓冲区)。

我认为这完全是在教科书中被告知的相反。有没有 是一些编译器优化,重新组织这种 方式的堆栈布局?

这似乎是唯一可能的解释,但我不知道..

如果你有兴趣,信息转储是由于缓冲区溢出通过 兵缓冲(但也印证&兵[0] < &缓冲区)。

谢谢!

+0

删除c标签,因为代码不是c。 – 2011-02-23 01:44:04

+1

@Stephen,你怎么知道在'main'之前没有'typedef char * string'? :-) – paxdiablo 2011-02-23 08:36:50

回答

9

编译器可以自由组织堆栈帧(假设它们即使是使用堆栈)也可以任意组织。

他们可能为了对齐的原因,或出于性能的原因,或者完全没有理由。假设任何特定的顺序是不明智的。

如果您没有通过溢出缓冲区来调用未定义的行为,那么您可能永远都不会知道,而这就是它应该的方式。

编译器不仅可以重新组织您的变量,还可以优化它们,如果它可以建立它们不被使用。随着代码:

#include <stdio.h> 
int main (void) { 
    char bing[71]; 
    int x = 7; 
    bing[0] = 11; 
    return 0; 
} 

比较正常的汇编输出:

main: 
    pushl %ebp 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $80, %esp 
    movl %gs:20, %eax 
    movl %eax, 76(%esp) 
    xorl %eax, %eax 
    movl $7, (%esp) 
    movb $11, 5(%esp) 
    movl $0, %eax 
    movl 76(%esp), %edx 
    xorl %gs:20, %edx 
    je  .L3 
    call __stack_chk_fail 
.L3: 
    leave 
    ret 

与疯狂优化:

main: 
    pushl %ebp 
    xorl %eax, %eax 
    movl %esp, %ebp 
    popl %ebp 
    ret 

发现任何从后者缺少什么?是的,有堆栈操作为bingx创建空间。他们不存在。事实上,整个代码序列归结为:

  • 集返回代码为0。
  • 回报。
+0

感谢您的详细输入! – Figo 2011-02-23 01:57:49

8

编译器可以自由地在堆栈上布局局部变量(或者将它们保存在寄存器中或者用它们做别的事情),但它看起来合适:C和C++语言标准对这些实现细节没有任何说明, POSIX或UNIX也不是。我怀疑你的教科书是否告诉过你,如果有的话,我会寻找一本新的教科书。

+0

感谢您的输入! – Figo 2011-02-23 01:57:22

+0

我想我必须从一些关于缓冲区溢出的教科书中读到它,它假定堆栈的布局关于如何编写代码:) – Figo 2011-02-23 01:59:31

+0

尽管你对标准是正确的,但教科书习惯于先过分简化,然后再纠正更高级课程中的具体细节。例如,你首先学习牛顿物理,然后他们告诉你它不能接近光速。编译器文本也不会让我感到惊讶。 – 2011-02-23 02:04:12