C++ 为什么缓冲区的结尾和保存的帧指针之间有8个字节?

C++ 为什么缓冲区的结尾和保存的帧指针之间有8个字节?,c++,c,linux,gcc,stack-overflow,C++,C,Linux,Gcc,Stack Overflow,我正在做一个课程作业的堆叠粉碎练习,我已经完成了作业,但有一个方面我不明白 以下是目标计划: #include <stdio.h> #include <stdlib.h> #include <string.h>

我正在做一个课程作业的堆叠粉碎练习,我已经完成了作业,但有一个方面我不明白

以下是目标计划:

#include <stdio.h>                                             
#include <stdlib.h>                                            
#include <string.h>                                            

int bar(char *arg, char *out)                                  
{                                                              
  strcpy(out, arg);                                            
  return 0;                                                    
}                                                              

void foo(char *argv[])                                         
{                                                              
  char buf[256];                                               
  bar(argv[1], buf);                                           
}                                                              

int main(int argc, char *argv[])                               
{                                                              
  if (argc != 2)                                               
    {                                                          
      fprintf(stderr, "target1: argc != 2\n");                 
      exit(EXIT_FAILURE);                                      
    }                                                          
  foo(argv);                                                   
  return 0;                                                    
}                                                              
当我查看堆栈上这个程序的内存时,我看到
buf
的地址是
0xbfffc40
。此外,保存的帧指针存储在
0xbfffd48
,返回地址存储在
0xbfffd4c

这些特定地址并不相关,但我观察到,即使
buf
只有长度
256
,距离
0xbffffd48-0xbffffc40=264
。从符号上讲,此计算是
$fp-buf

为什么在
buf
的结尾和堆栈上存储的帧指针之间有
8个
额外字节?

下面是对函数
foo
的一些反汇编。我已经检查过了,但我没有看到该记忆区域有任何明显的用途,除非它是隐式的(即某些指令的副作用)

0x080484ab:推送%ebp
0x080484ac:mov%esp,%ebp
0x080484ae:低于$0x118,%esp
0x080484b4:mov 0x8(%ebp),%eax
0x080484b7:添加$0x4,%eax
0x080484ba:mov(%eax),%eax
0x080484bc:lea-0x108(%ebp),%edx
0x080484c2:mov%edx,0x4(%esp)
0x080484c6:mov%eax,(%esp)
0x080484c9:调用0x8048C
0x080484ce:离开
0x080484cf:ret

Basile Starynkevitch因提及对齐而获奖

结果是,
gcc4.7.2
默认将框架边界与4字边界对齐。在32位模拟硬件上,即16字节。由于保存的帧指针和保存的指令指针一起只占用8个字节,编译器在
buf
结束后再放入8个字节,以将堆栈帧的顶部与16字节边界对齐

-mpreferred-stack-boundary=2
使用以下附加编译器标志,8个字节将消失,因为8个字节足以对齐到2字边界

-mpreferred-stack-boundary=2

因为帧通常与16字节对齐(或者可能是8字节,我忘记了细节)。@BasileStrynkevitch,地址
0xbffffc40
已经与16字节对齐,256肯定是16的倍数。该区域用于存储寄存器吗?'buf'不包含地址。它有一个地址。@MantoshKumar,请注意编译器标志
-fno stack protector
-mpreferred-stack-boundary=2