gpt4 book ai didi

c - GCC 如何初始化自动变量?它们保证为 0 吗?

转载 作者:太空宇宙 更新时间:2023-11-04 01:00:39 25 4
gpt4 key购买 nike

我为以下 C 代码生成了未优化的代码:

#include<stdio.h>
int main(){
int i;
printf("%d\n", i);
}

生成的代码是:

    .file   "test.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits

运行上面的汇编代码给出 0 作为输出。我的问题是,变量 i 是如何初始化为 0 的?

最佳答案

NPE's answer告诉您 C 标准必须说明的关于这个程序的一切:行为是(完全)未定义的。

现在编译器已经生成了 Linux 上的 gcc -O0 未优化的 asm,我会尝试解释一下为什么您碰巧从该未优化的 asm 中得到零。

正如哈罗德指出的那样,它从堆栈内存中读取它没有写入的内容。 Linux 内核为您的进程提供其堆栈的零页,以避免信息泄漏。 (与 mmap(MAP_ANONYMOUS) 相同)

在调用 printf 之前,没有任何启动代码使用与 main 一样多的堆栈空间,因此从它加载的代码仍然会找到初始置零状态。

当然,printf返回后,RSP下面的栈就脏了。动态链接是“延迟”完成的,所以它发生在 call printf 之后(实际上是 call printf@plt 如果你用 objdump 反汇编链接的目标文件-drwC -Mintel a.out).这可能会使用一些堆栈空间进行临时存储。 (如果你曾经单步进入动态链接二进制文件中对库函数的第一次调用,你会在执行到达实际库函数代码之前看到大约 100 万条指令。[我忘记了我是如何测量这个数字的,但我似乎回想起来做的事情告诉我它可能有大约 1M 条指令。]) printf 本身肯定会压入/弹出一些寄存器,并且可能会使用堆栈上的一些其他暂存空间。

关于c - GCC 如何初始化自动变量?它们保证为 0 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41079465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com