为什么未初始化的全局变量是弱符号? [英] Why uninitialized global variable is weak symbol?
问题描述
这似乎未初始化的全局变量被视为gcc的弱符号。这背后有什么原因呢?
It seems uninitialized global variable is treated as weak symbol in Gcc. What is the reason behind this?
推荐答案
GCC,在C模式:
这是没有申报的extern
被视为共同的符号,不弱的符号。未初始化的全局
Uninitialised globals which are not declared extern
are treated as "common" symbols, not weak symbols.
通用符号在链接时合并,以便它们都指的是同一个存储;如果有多个对象尝试初始化这样的符号,你会得到一个链接时错误。 (如果不明确地初始化的任何地方,它们将被放置在BSS,即,初始化为0。)
Common symbols are merged at link time so that they all refer to the same storage; if more than one object attempts to initialise such a symbol, you will get a link-time error. (If they aren't explicitly initialised anywhere, they will be placed in the BSS, i.e. initialised to 0.)
GCC,在C ++模式:
不一样 - 它不这样做的常用符号的东西。这是不是宣称的未初始化全局的extern
被隐式初始化为默认值(0简单类型,或默认构造函数)。
Not the same - it doesn't do the common symbols thing. "Uninitialised" globals which are not declared extern
are implicitly initialised to a default value (0 for simple types, or default constructor).
在任一情况下,弱符号允许初始化符号用相同的名称的一个非弱初始化符号在链接时被覆盖。
In either case, a weak symbol allows an initialised symbol to be overridden by a non-weak initialised symbol of the same name at link time.
要说明(集中在C的情况下在这里),我将使用一个主程序4变种,这是除了为全球
就是这样,都是一样的声明:
To illustrate (concentrating on the C case here), I'll use 4 variants of a main program, which are all the same except for the way that global
is declared:
-
main_init.c
#include <stdio.h>
int global = 999;
int main(void) { printf("%d\n", global); return 0; }
main_uninit.c ,它省略了初始化:
#include <stdio.h>
int global;
int main(void) { printf("%d\n", global); return 0; }
main_uninit_extern.c ,它增加了的extern
关键字:
#include <stdio.h>
extern int global;
int main(void) { printf("%d\n", global); return 0; }
main_weak_init.c ,它初始化全球
并声明这是一个弱符号:
main_weak_init.c, which initialises global
and declares it to be a weak symbol:
#include <stdio.h>
int global __attribute__((weak)) = 999;
int main(void) { printf("%d\n", global); return 0; }
和 another_def.c 哪些初始化相同的全局:
and another_def.c which initialises the same global:
int global = 1234;
使用 main_uninit.c
对自己给出了0:
$ gcc -o test main_uninit.c && ./test
0
但 another_def.c
也包括在内,全球
明确初始化,我们得到预期的结果:
but when another_def.c
is included as well, global
is explicitly initialised and we get the expected result:
$ gcc -o test main_uninit.c another_def.c && ./test
1234
(请注意,这种情况下,而不是失败,如果你使用C ++)。
(Note that this case fails instead if you're using C++.)
如果我们试图用两个 main_init.c
和 another.def.c
相反,我们有2个initialisations的全球
,这是行不通的:
If we try with both main_init.c
and another.def.c
instead, we have 2 initialisations of global
, which won't work:
$ 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
关键字使符号是一个普通的外部参考,而不是常见的象征,因此链接器抱怨:
main_uninit_extern.c
on its own won't work at all - the extern
keyword causes the symbol to be an ordinary external reference rather than a common symbol, so the linker complains:
$ 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),因为没有什么可以替代它:
Using main_init_weak.c
on its own gives the value we initialised the weak symbol to (999), as there is nothing to override it:
$ gcc -o test main_init_weak.c && ./test
999
但是,在从 another_def.c
其他定义拉动确实在这种情况下工作,因为强烈的定义有覆盖 main_init_weak弱定义。 ç
:
But pulling in the other definition from another_def.c
does work in this case, because the strong definition there overrides the weak definition in main_init_weak.c
:
$ gcc -o test main_init_weak.c another_def.c && ./test
1234
这篇关于为什么未初始化的全局变量是弱符号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!