堆栈变量是否在虚拟内存中连续分配?

时间:2015-06-29 17:09:12

标签: c linux memory assembly virtual-memory

我正在用C编译以下程序:

void function(int a, int b, int c) {
char buffer1[11];
char buffer2[3];
char buffer3[1];
char buffer4[1];
}

void main() {
function(1,2,3);
}

使用命令:

gcc -m32 -fno-asynchronous-unwind-tables -fno-stack-protector -S -o example1.s example1.c

以下是我得到的输出:

    .file   "example1.c"
    .text
    .globl  function
    .type   function, @function
function:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $16, %esp
    leave
    ret
    .size   function, .-function
    .globl  main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    pushl   $3
    pushl   $2
    pushl   $1
    call    function
    addl    $12, %esp
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
    .section    .note.GNU-stack,"",@progbits

subl $ 16 ,%esp 这一行表示在堆栈上分配了16个字节。

但是根据不同的教程,我可以看到堆栈空间通常分配为4个字节的块。

为什么我看到的行为有所不同?

我正在运行64位Ubuntu系统: -

vendor_id   : GenuineIntel
cpu family  : 6
model       : 58
model name  : Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
stepping    : 9
microcode   : 0x1b
cpu MHz     : 1202.636
cache size  : 3072 KB
physical id : 0
siblings    : 4
core id     : 0
cpu cores   : 2
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 13
wp      : yes
bugs        :
bogomips    : 4988.46
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

任何人都可以帮助我理解这一点。

我在下面提到的问题:How is memory allocated for stack variables? 但是我无法找到具体的答案。

编辑: 1)我想了解整个堆栈是否必须与4/8/16字节边界对齐或每个堆栈变量必须。 2)可以组合成堆栈存储器的局部变量类型是否有任何限制?

2 个答案:

答案 0 :(得分:3)

“1)我想了解整个堆栈是否必须与4/8/16位边界或每个堆栈变量必须对齐。”

这是一个机器和编译器特定的问题。通常,变量根据其大小和CPU字大小进行对齐。在32位CPU上对32位边界上的32位变量进行对齐有一个巨大的优势,但在8位CPU(如8051)上对齐32位变量没有任何优势.32位CPU如果它们在32位边界(0x ?? 0,0x ?? 4,0x ?? 8,0x ?? c)上对齐,则只能将32位值作为32位值处理。

2)可以组合成堆栈存储器的局部变量类型是否有任何限制?

除了对齐之外没有其他限制。

答案 1 :(得分:2)

答案是堆栈变量不必连续分配。在许多情况下,他们不太可能。

如果你有

{
   struct
   {
      int a ;
      char b ;
      double c ;
      char d ;
   } x, y, z; 
}

我敢打算大多数编译器不会使x,y和z连续。

无论如何,您所要求的完全取决于系统和编译器。编译器根本不必在堆栈上放置自动变量。