链接器如何定义多处解析的全局符号.docxVIP

  • 2
  • 0
  • 约2.05千字
  • 约 5页
  • 2017-02-23 发布于四川
  • 举报

链接器如何定义多处解析的全局符号.docx

链接器如何定义多处解析的全局符号

链接器如何定义多处解析的全局符号基本介绍:在编译时,编译器输出每个全局符号给汇编器,或者是强(strong),或者是弱(weak),而汇编器把这个信息隐含地编码在可重定位目标文件的符号表里。函数和以函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。我们也可以通过GCC的__attribute__((weak))来定义任何一个强符号为弱符号。注意,强符号和弱符号都是针对定义来说的,不是针对符号的引用。比如我们有下面这段程序:extern int ext;int weak;int strong = 1;__attribute__((weak)) weak2 = 2;int main(){return 0;}weak,weak2是弱符号。strong,main是强符号,而ext既非强符号也非弱符号。因为它是一个外部变量的引用。针对强弱符号的概念,链接器就会按如下规则处理与选择被多次定义的全局符号:规则1:不允许强符号被多次定义(即不同的目标文件中不能有同名的强符号);如果有多个强符号定义,则链接器报符号重复定义错误。规则2:如果一个符号在某个目标文件中是强符号,在其他文件中都是弱符号,那么选择强符号。规则3:如果一个符号在所有目标文件中都是弱符号,那么选择其中占用空间最大的一个。比如目标文件A定义全局变量global为int型,占4个字节;目标文件B定义global为double型,占8个字节,那么目标文件A和B链接后,符号global占8个字节(尽量不要使用多个不同类型的弱符号,否则容易导致很难发现的程序错误)。示例:1. //bar.cint main(){return 0;} //foo.cint main(){return 0;}链接器将生成一条错误信息:$ gcc foo.c bar.c /tmp/ccgVHUSN.o: In function `main:bar.c:(.text+0x0): multiple definition of `main/tmp/ccCZ9xqQ.o:foo.c:(.text+0x0): first defined herecollect2: ld returned 1 exit status因为强符号main被定义了多次(规则1)。2.修改一下://foo.cint x = 2;int main(){return 0;}//bar.cint x = 1;void f(){}$ gcc foo.c bar.c /tmp/cczbmyHW.o:(.data+0x0): multiple definition of `x/tmp/ccsAcjCn.o:(.data+0x0): first defined herecollect2: ld returned 1 exit status因为强符号x被定义了多次(规则1)。3.如果在一个模块里x未被初始化,那么链接器将安静的选择定义在另一个模块中的强符号(规则2)。//bar.cint x;void f(){x = 100;}//foo.cint x = 2;void f();int main(){f();printf(x = %d\n,x);return 0;}运行结果:x = 100。在运行时,函数f将x的值由2改为100。要注意这种情况。4.如果x有两个弱定义,也会发生相同的事情。(规则3)//foo.cint x;void f();int main(){x = 2;f();printf(x = %d\n,x);return 0;}//bar.cint x;void f(){x = 100;}5.当两个重复的符号类型不同时://bar.cdouble x;void f(){x = -0.0;}//foo.cint x = 1;int y = 2;void f();int main(){f();printf(x = %x,y = %x\n,x,y);return 0;}$ gcc bar.c foo.cfoo.c: In function ‘main’:foo.c:9: warning: incompatible implicit declaration of built-in function ‘printf’/usr/bin/ld: Warning: alignment 4 of symbol `x in /tmp/ccVLU2rl.o is smaller than 8 in /tmp/ccUQq1xX.o/usr/bin/ld: Warning: size of symbol `x changed from 8 in /tmp/ccUQq1xX.o to 4 in /tmp/ccVLU2rl.o$ ./a.out x = 0,y

您可能关注的文档

文档评论(0)

1亿VIP精品文档

相关文档