CSAPP - Linking - Strong and weak symbols
Posted on 2007-08-02 23:45 ZelluX 閱讀(871) 評(píng)論(0) 編輯 收藏 所屬分類: C/C++ 、System《竊聽風(fēng)暴》的男主角烏爾里希·穆埃(Ulrich Mühe)
病逝了。。。
好片子,好演員,可惜了。。。
CSAPP 第七章Linking太枯燥了
啃了半天總算看到一點(diǎn)實(shí)際經(jīng)歷中遇到過的。
在編譯階段,編譯器把全局變量標(biāo)記為strong或者weak,并導(dǎo)出到匯編程序中,由匯編程序把這些信息隱式地添加到relocatable object file的符號(hào)表(symbol table)中。
函數(shù)和被初始化的全局變量被標(biāo)記為strong,未初始化的全局變量被標(biāo)記為weak。
Unix連接器(linker)使用下面的規(guī)則來(lái)處理多個(gè)符號(hào)的情況:
1. 不允許多個(gè)strong symbol的存在
2. 如果有一個(gè)strong symbol和若干個(gè)weak symbol,使用strong symbol
3. 只有若干個(gè)weak symbol,則使用其中任意一個(gè)
幾個(gè)例子(未特殊說(shuō)明的情況,變量定義均在全局范圍):
1. foo1.c和bar1.c中都有int main()方法,即存在了兩個(gè)strong symbol,連接器就會(huì)產(chǎn)生一條錯(cuò)誤信息。
2.
注意這可能不是main()方法的作者原來(lái)的意圖。
類似的情況也可能發(fā)生在兩個(gè)weak symbol同名的時(shí)候。
3. 全局變量類型不同的情況:
linux> gcc -o foobar5 foo5.c bar5.c
linux> ./foobar5
結(jié)果應(yīng)該是
x = 0x0 y = 0x80000000
但是在自己機(jī)器上編譯時(shí)報(bào)錯(cuò)了,可能連接器版本較高,會(huì)自動(dòng)找出這種錯(cuò)誤
/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o
是double和int大小不義導(dǎo)致的對(duì)齊問題
這些問題都比較細(xì)小難以被查覺,通常在程序執(zhí)行了一段時(shí)間后才出現(xiàn)較嚴(yán)重的問題,因此很難被修復(fù),尤其當(dāng)許多程序員不清楚連接器的工作方式的時(shí)候。
另外可以使用GCC的-warn-common標(biāo)記(flag),使得它在解析多個(gè)同名的全局變量時(shí)發(fā)出警告。
試了下沒成功@@
gcc --warn-common提示無(wú)法識(shí)別的命令行選項(xiàng),gcc -Wall則不會(huì)發(fā)出警告。
好片子,好演員,可惜了。。。
CSAPP 第七章Linking太枯燥了

在編譯階段,編譯器把全局變量標(biāo)記為strong或者weak,并導(dǎo)出到匯編程序中,由匯編程序把這些信息隱式地添加到relocatable object file的符號(hào)表(symbol table)中。
函數(shù)和被初始化的全局變量被標(biāo)記為strong,未初始化的全局變量被標(biāo)記為weak。
Unix連接器(linker)使用下面的規(guī)則來(lái)處理多個(gè)符號(hào)的情況:
1. 不允許多個(gè)strong symbol的存在
2. 如果有一個(gè)strong symbol和若干個(gè)weak symbol,使用strong symbol
3. 只有若干個(gè)weak symbol,則使用其中任意一個(gè)
幾個(gè)例子(未特殊說(shuō)明的情況,變量定義均在全局范圍):
1. foo1.c和bar1.c中都有int main()方法,即存在了兩個(gè)strong symbol,連接器就會(huì)產(chǎn)生一條錯(cuò)誤信息。
2.
/* foo3.c */
#include <stdio.h>
void f(void);
int x = 15213;
int main()
{
f();
printf("x = %d\n", x);
return 0;
}
#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()方法調(diào)用f()后,x變?yōu)?5212并被輸出。int x;
void f()
{
x = 15212;
}
注意這可能不是main()方法的作者原來(lái)的意圖。
類似的情況也可能發(fā)生在兩個(gè)weak symbol同名的時(shí)候。
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;
}
#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;
}
根據(jù)書上的內(nèi)容,double x;
void f()
{
x = -0.0;
}
linux> gcc -o foobar5 foo5.c bar5.c
linux> ./foobar5
結(jié)果應(yīng)該是
x = 0x0 y = 0x80000000
但是在自己機(jī)器上編譯時(shí)報(bào)錯(cuò)了,可能連接器版本較高,會(huì)自動(dòng)找出這種錯(cuò)誤

/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o
是double和int大小不義導(dǎo)致的對(duì)齊問題
這些問題都比較細(xì)小難以被查覺,通常在程序執(zhí)行了一段時(shí)間后才出現(xiàn)較嚴(yán)重的問題,因此很難被修復(fù),尤其當(dāng)許多程序員不清楚連接器的工作方式的時(shí)候。
另外可以使用GCC的-warn-common標(biāo)記(flag),使得它在解析多個(gè)同名的全局變量時(shí)發(fā)出警告。
試了下沒成功@@
gcc --warn-common提示無(wú)法識(shí)別的命令行選項(xiàng),gcc -Wall則不會(huì)發(fā)出警告。