GCC編譯C語言時,如果加的.a庫裡面和C源文件同時有某個函數或者某個全局變數,GCC會用哪個?


這個跟強符號弱符號有關。我記得在《程序員的自我修養:鏈接裝載與庫》和《深入理解計算機系統》裡面都有說過,規則我記得應該是這樣(建議題主還是去看看書,描述的更詳細):

函數和初始化了的全局變數是強符號,未初始化的全局變數是弱符號。鏈接的時候遇到同名的符號是這樣處理的:

1.同名的裡面有多個強符號,連接錯誤

2.一強一個或多個弱,選強符號,但是可能有警告

3.都是弱符號,選佔用空間最大的那個..


根據標準,鏈接的時候,可以在所有引用到這個變數的地方,隨機選擇一個。


這麼干不就是坑隊友么


我寫一個例子,

echo "int a = 100;" &> a1.c;
echo "int a = 200;" &> a2.c;
gcc -c -o a1.o a1.c;
gcc -c -o a2.o a2.c;
ar cr liba.o a1.o
cat &<& foo.c
#include &
extern int a;
int main(int argc, char * argv[])
{
printf("a=%d
",a);
return 0;
}
EOF

如果使用

bash$ gcc -L. -o a.out foo.c -la a2.o
# 很好出錯
a2.o:(.data+0x0): multiple definition of `a"
./liba.a(a1.o):(.data+0x0): first defined here
collect2: error: ld returned 1 exit status

如果使用

bash$ gcc -L. -o a.out foo.c a2.o -la
# 這個風險最大
bash$ ./a.out
a=200

如果使用

bash$ gcc -L. -o a.out foo.c a2.o a1.o # 很好,出錯
a1.o:(.data+0x0): multiple definition of `a"
a2.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
bash$ gcc -L. -o a.out foo.c a1.o a2.o
a2.o:(.data+0x0): multiple definition of `a"
a1.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status

總之,這是一個實現相關的事。最好別這麼干。


如果符號真的完全相同,鏈接器直接報錯。

當你發現居然可以鏈接通過,那就要小心了。仔細看看 .o 中的符號 和 .a 中的符號完全一致嗎?用 nm 來看看吧。

我的經驗是:gcc非常嚴謹,絕對不會出現模稜兩可的情況。如果覺得發現了奇妙的事情,多半是自己搞錯了。


第一個,詳見《程序員的自我修養:鏈接裝載與庫》


推薦閱讀:

一段程序在gcc 5.4下編譯後,執行發生段錯誤,在gcc 4.4.7下編譯後,執行正常,什麼原因?
C++在類模板中如何定義友元函數為同類型的模板函數?
為什麼 C 語言的輸入輸出函數比 C++ 的輸入輸出流要快?
有沒有比較好的自學IT的網站?適用於不管是初學者還是其他段位的程序猿的網站?
如何評價2016年藍橋杯決賽?

TAG:C編程語言 | CC | GCC |