posts - 403, comments - 310, trackbacks - 0, articles - 7
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

CSAPP - Linking - Strong and weak symbols

Posted on 2007-08-02 23:45 ZelluX 阅读(857) 评论(0)  编辑  收藏 所属分类: C/C++System
《窃听风暴》的男主角乌尔里希·穆埃(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则不会发出警告。

只有注册用户登录后才能发表评论。


网站导航: