为什么我的编译器会保留比函数堆栈帧所需的空间更多的空间?

时间:2013-10-21 04:55:21

标签: assembly stack

我有一个功能:

void func(int a)
{
    int x = a+2;
}

在汇编代码中,在函数prolog中:

push %ebp
mov %esp, %ebp
sub $0x10, %esp

代码只需要为x保留空间,即4个字节。但它保留了16个字节。这是为什么 ?我一直认为它可以保留比所需更多的空间。

我的猜测:它倾向于以16个字节存储。即如果我需要说20个字节,它将保留32个字节,无论如何。

1 个答案:

答案 0 :(得分:5)

这在很大程度上取决于你的体系结构和编译器标志,因此不可能指向一个单一的东西并且说'#34;这必须是它"这里。但是,我可以给你一些你可能会发现有帮助的建议。

首先,考虑堆栈边界。您可能听说过GCC的-mpreferred-stack-boundary = X标志。如果没有,它基本上告诉编译器更喜欢堆栈上的值为2 ^ X字节。然后,您的编译器将尝试优化您的程序,以便这些值尽可能地适合堆栈。另一方面,GCC修饰符如__packed__将使编译器尽可能紧密地拟合堆栈中的数据。

还有堆栈保护器。基本上,GCC会在堆栈上放置虚拟值,以确保缓冲区溢出除了破坏程序之外不会造成任何伤害(这不是有趣的,但比攻击者控制指令指针更好)。您可以轻松地尝试这一点:使用任何最新版本的GCC并让用户溢出缓冲区。您将注意到程序退出时会显示“'堆栈粉碎检测到,已终止'”的消息。尝试使用-fno-stack-protector编译程序,堆栈上分配的本地内存可能会更小。