天天看點

linux中連結順序問題

文章目錄

    • 問題
    • 環境
    • 檔案邏輯
    • 動态編譯
      • 編譯成動态庫
      • 使用g++連結
      • 使用clang++連結
    • 靜态連結
      • 編譯成靜态庫
      • 使用g++連結
      • 使用clang++連結同g++。
    • 結論

問題

讨論了一下動态連結和靜态連結的問題,即在連結過程中到底是以什麼順序進行連結的,中間會不會儲存一部分資訊到符号表中。

環境

Ubuntu 14.04.6 LTS

g++ (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010

Ubuntu clang version 3.4-1ubuntu3

檔案邏輯

main.cc調用test.cc,test.cc調用test2.cc

// main.cc
#include "test.h"
int main()
{
    test();
    return 0;
}
           
// test.cc
#include "test2.h"
void test()
{
    test2();
}
           
// test2.cc
#include <iostream>
using namespace std;
void test2()
{
    cout << "test2" << endl;
}
           

動态編譯

編譯成動态庫

g++ test.cc -shared -fPIC -o libtest.so
g++ test2.cc  -shared -fPIC -o libtest2.so
           

使用g++連結

g++ main.cc -o main -L./ -ltest -ltest2 -I./
g++ main.cc -o main -L./ -ltest2 -ltest -I./
           

第一條語句報錯

.//libtest.so: undefined reference to `test2()’

collect2: error: ld returned 1 exit status

第二條語句連結成功

使用clang++連結

clang++ main.cc -o main -L./ -ltest -ltest2 -I./
clang++ main.cc -o main -L./ -ltest2 -ltest -I./
           

兩條語句均可正常連結

靜态連結

編譯成靜态庫

g++ -c test.cc
g++ -c test2.cc

ar -rc test.a test.o
ar -rc test2.a test2.o
           

使用g++連結

g++ main.cc test.a test2.a  -o main
g++ main.cc test2.a test.a -o main
           

第一條語句正常執行

第二條語句報錯

test.a(test.o): In function

test()': test.cc:(.text+0x5): undefined reference to

test2()’

collect2: error: ld returned 1 exit status

使用clang++連結同g++。

結論

網上那些文章不靠譜哇。

g++不論是靜态連結還是動态連結,都需要以正确的順序進行連結,即基礎類放在最右面。原理應該是g++從左向右掃描所有連結庫,遇到連結庫中不認識的符号就放在一個undefined表中,如果在後面的庫中發現這個符号就填上正确的位置,沒發現則最後連結報錯。

clang++動态連結過程中會自動識别連結的順序,靜态連結需要手動調整順序。

繼續閱讀