CSAPP - Linking - Strong and weak symbols

《窃听风暴》的男主角乌尔里希·穆埃(Ulrich Mühe) 病逝了。。。
好片子,好演员,可惜了。。。

CSAPP 第七章Linking太枯燥了   啃了半天总算看到一点实际经历中遇到过的。

在编译阶段,编译器把全局变量标记为strong或者weak,并导出到汇编程序中,由汇编程序把这些信息隐式地添加到relocatable object file的符号表(symbol table)中。
函数和被初始化的全局变量被标记为strong,未初始化的全局变量被标记为weak。
Unix连接器(linker)使用下面的规则来处理多个符号的情况:
1. 不允许多个strong symbol的存在
2. 如果有一个strong symbol和若干个weak symbol,使用strong symbol
3. 只有若干个weak symbol,则使用其中任意一个

几个例子(未特殊说明的情况,变量定义均在全局范围):
1. foo1.c和bar1.c中都有int main()方法,即存在了两个strong symbol,连接器就会产生一条错误信息。
2.
/* foo3.c */
#include 
< stdio.h >
void  f( void );

int  x  =   15213 ;

int  main()
{
    f();
    printf(
" x = %d\n " , x);
    
return   0 ;
}

/*  bar3.c  */
int  x;

void f()
{
    x 
=   15212 ;
}
main()方法调用f()后,x变为15212并被输出。
注意这可能不是main()方法的作者原来的意图。
类似的情况也可能发生在两个weak symbol同名的时候。

3. 全局变量类型不同的情况:
/*  foo5.c  */
#include 
< stdio.h >
void  f( void );

int  x  =   15213 ;
int  y  =   15212 ;

int  main()
{
    f();
    printf(
" x = 0x%x  y = 0x%x \n " , x, y);
    
return   0 ;
}

/*  bar4.c  */
double x;

void  f()
{
    x 
=   - 0.0 ;
}
根据书上的内容,
linux> gcc -o foobar5 foo5.c bar5.c
linux> ./foobar5
结果应该是
x = 0x0  y = 0x80000000

但是在自己机器上编译时报错了,可能连接器版本较高,会自动找出这种错误
/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o
是double和int大小不义导致的对齐问题


这些问题都比较细小难以被查觉,通常在程序执行了一段时间后才出现较严重的问题,因此很难被修复,尤其当许多程序员不清楚连接器的工作方式的时候。
另外可以使用GCC的-warn-common标记(flag),使得它在解析多个同名的全局变量时发出警告。
试了下没成功@@
gcc --warn-common提示无法识别的命令行选项,gcc -Wall则不会发出警告。

你可能感兴趣的:(CSAPP - Linking - Strong and weak symbols)