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

标签 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) 可以组合成一个字的栈内存的局部变量的类型有没有限制?

最佳答案

“1) 我想了解是整个堆栈只需要与 4/8/16 位边界对齐,还是每个堆栈变量都必须对齐。”

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

2) 可以组合成一个字的栈内存的局部变量的类型有没有限制?

除了对齐之外没有限制。

关于c - 堆栈变量是否在虚拟内存中连续分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31121579/

相关文章:

linux - 什么是抢占/什么是可抢占内核?到底有什么好处呢?

linux - 从 ls 中排除某些目录并将其余目录复制到共享路径

linux - 在循环 bash 中等待

javascript - 我应该将 document.getElementById() 缓存在变量中还是每次都调用它?

c - 用户空间中的物理内存管理?

c++ - 尝试设置一个数组以将最后三笔存款存储到银行账户系统中

c - Visual Studio C 编译器是否具有与 GCC 的 -M 等效的功能?

c - 如何将十六进制存储在 uint8_t 数组中?

c - gnu 库 C 中的 libc_hidden_​​proto 宏

c - OpenMP 线程处理的迭代索引