C 缓冲区分配不是字大小的倍数

C 缓冲区分配不是字大小的倍数,c,memory-management,gdb,stack,buffer-overflow,C,Memory Management,Gdb,Stack,Buffer Overflow,我写了一个小程序来了解堆栈的结构 #include <stdio.h> void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret = buffer1 + 13; (*ret) += 8; } int main() { int x = 0; function(1,2,3); x = 1; printf("x = %

我写了一个小程序来了解堆栈的结构

#include <stdio.h>

void function(int a, int b, int c) {
    char buffer1[5];
    char buffer2[10];

    int *ret = buffer1 + 13;
    (*ret) += 8;
}

int main() {
    int x = 0;
    function(1,2,3);
    x = 1;
    printf("x = %d\n",x);
    return 0;
}
我还了解到,如果我们分配5个字节的数据,程序分配8个字节(因为它必须是字大小的倍数)

函数
函数
的汇编程序代码转储:

0x08048414 <+0>:    push   %ebp
0x08048415 <+1>:    mov    %esp,%ebp
0x08048417 <+3>:    sub    $0x20,%esp
0x0804841a <+6>:    lea    -0x9(%ebp),%eax
0x0804841d <+9>:    add    $0xd,%eax
0x08048420 <+12>:   mov    %eax,-0x4(%ebp)
0x08048423 <+15>:   mov    -0x4(%ebp),%eax
0x08048426 <+18>:   mov    (%eax),%eax
0x08048428 <+20>:   lea    0x8(%eax),%edx
0x0804842b <+23>:   mov    -0x4(%ebp),%eax
0x0804842e <+26>:   mov    %edx,(%eax)
0x08048430 <+28>:   leave  
0x08048431 <+29>:   ret    
这是我的疑问
buffer1
buffer2
之间的差异怎么可能是
10
,当所有内容都以字数的倍数分配时

%ebp和
buffer1
之间的
9
有什么区别

这里到底发生了什么

注意

  • 考虑堆栈从高到低的增长
  • 字号=4
  • 我使用的是英特尔处理器、Ubuntu 12.04、32位和

    gcc-o stack-g-fno stack protector-O0 main.c

建造

我怀疑,当所有内容都以字大小的倍数分配时,buffer1和buffer2之间的差异怎么可能是0x10

首先,更正:
buffer1
buffer2
之间的差异是
10
,而不是
0x10
(即
16


第二,并非所有内容都以多个单词的形式分配。总帧大小至少可以被8整除,以保持堆栈正确对齐
双倍
,但单个局部变量将仅按照其对齐要求进行对齐(对于字符和字符缓冲区,这是
1
)。

编译器可以自由安排堆栈,但它认为合适。。。。。。字符数组不需要分配到4(甚至2)的倍数的地址上。它们可以在奇数边界上对齐。在大多数机器上,大多数其他基本类型将根据类型的大小在基本大小(2、4、8、16字节)的倍数边界上分配。有时,较大的类型只需要分配4字节的倍数。如果试图覆盖对齐要求,通常会失去性能—例如,通过包装结构。对于有同样疑问的人,我建议阅读Jonathan的评论。
0x08048414 <+0>:    push   %ebp
0x08048415 <+1>:    mov    %esp,%ebp
0x08048417 <+3>:    sub    $0x20,%esp
0x0804841a <+6>:    lea    -0x9(%ebp),%eax
0x0804841d <+9>:    add    $0xd,%eax
0x08048420 <+12>:   mov    %eax,-0x4(%ebp)
0x08048423 <+15>:   mov    -0x4(%ebp),%eax
0x08048426 <+18>:   mov    (%eax),%eax
0x08048428 <+20>:   lea    0x8(%eax),%edx
0x0804842b <+23>:   mov    -0x4(%ebp),%eax
0x0804842e <+26>:   mov    %edx,(%eax)
0x08048430 <+28>:   leave  
0x08048431 <+29>:   ret    
(gdb) x/x $ebp
    0xbffff318: 0xbffff348
(gdb) x/x buffer1
    0xbffff30f: 0xfc73e461
(gdb) x/x buffer2
    0xbffff305: 0x0108049f