gpt4 book ai didi

c++ - 为什么未初始化的全局变量是弱符号?

转载 作者:可可西里 更新时间:2023-11-01 16:52:22 32 4
gpt4 key购买 nike

似乎未初始化的全局变量在 Gcc 中被视为弱符号。这背后的原因是什么?

最佳答案

gcc,C 模式:

未声明 extern 的未初始化全局变量被视为“通用”符号,而不是弱符号。

公共(public)符号在链接时合并,以便它们都引用相同的存储;如果不止一个对象试图初始化这样一个符号,您将得到一个链接时错误。 (如果它们没有在任何地方显式初始化,它们将被放置在 BSS 中,即初始化为 0。)

gcc,在 C++ 模式下:

不一样 - 它不做常见符号的事情。未声明为 extern 的“未初始化”全局变量被隐式初始化为默认值(简单类型或默认构造函数为 0)。


无论哪种情况,弱符号都允许初始化符号在链接时被同名的非弱初始化符号覆盖。


为了说明(这里集中在 C 案例上),我将使用一个主程序的 4 个变体,除了声明 global 的方式外,它们都是相同的:

  1. ma​​in_init.c:

    #include <stdio.h>

    int global = 999;

    int main(void) { printf("%d\n", global); return 0; }
  2. ma​​in_uninit.c,省略了初始化:

    #include <stdio.h>

    int global;

    int main(void) { printf("%d\n", global); return 0; }
  3. ma​​in_uninit_extern.c,其中添加了extern关键字:

    #include <stdio.h>

    extern int global;

    int main(void) { printf("%d\n", global); return 0; }
  4. ma​​in_init_weak.c,初始化 global 并将其声明为弱符号:

    #include <stdio.h>

    int global __attribute__((weak)) = 999;

    int main(void) { printf("%d\n", global); return 0; }

和初始化相同全局的another_def.c:

int global = 1234;

单独使用 main_uninit.c 得到 0:

$ gcc -o test main_uninit.c && ./test
0

但是当 another_def.c 也包含在内时,global 被显式初始化,我们得到了预期的结果:

$ gcc -o test main_uninit.c another_def.c && ./test
1234

(请注意,如果您使用的是 C++,则这种情况会失败。)

如果我们尝试同时使用 main_init.canother.def.c,我们有 2 个 global 初始化,它们不会工作:

$ gcc -o test main_init.c another_def.c && ./test
/tmp/cc5DQeaz.o:(.data+0x0): multiple definition of `global'
/tmp/ccgyz6rL.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

main_uninit_extern.c 本身根本不起作用 - extern 关键字导致符号成为普通的外部引用而不是公共(public)符号,因此链接器提示:

$ gcc -o test main_uninit_extern.c && ./test
/tmp/ccqdYUIr.o: In function `main':
main_uninit_extern.c:(.text+0x12): undefined reference to `global'
collect2: ld returned 1 exit status

一旦包含来自 another_def.c 的初始化,它就可以正常工作:

$ gcc -o test main_uninit_extern.c another_def.c && ./test
1234

单独使用 main_init_weak.c 给出我们将弱符号初始化为 (999) 的值,因为没有任何东西可以覆盖它:

$ gcc -o test main_init_weak.c && ./test
999

但是从 another_def.c 中引入另一个定义在这种情况下确实有效,因为那里的强定义覆盖了 main_init_weak.c 中的弱定义:

$ gcc -o test main_init_weak.c another_def.c && ./test
1234

关于c++ - 为什么未初始化的全局变量是弱符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3691835/

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