http://www.cnblogs.com/glacierh/p/4678667.html2015 庫文件依賴順序GCC在鏈接時(shí)對依賴庫的順序是敏感的,被依賴的庫必須放在后面,比如liba.a依賴libb.a,必須寫成liba.a libb.a,否則鏈接將出錯(cuò)。在庫比較多依賴關(guān)系比較復(fù)雜或者相互依賴或者自己不清楚的情況下,可以使用下面的選項(xiàng)來強(qiáng)制GCC重復(fù)查找依賴庫: g++ -o tt tt.o -Xlinker "-(" -lws2_32 -lclsocketd -Xlinker "-)" 強(qiáng)符號和弱符號在鏈接中,如果多個(gè)目標(biāo)文件中含有相同名字的全局符號的定義,鏈接器是怎么進(jìn)行處理的?這里就涉及到強(qiáng)符號和弱符號的問題,編譯器默認(rèn)函數(shù)和初始化了的全局變量為強(qiáng)符號,未初始化的全局變量為弱符號,強(qiáng)符號和弱符號都是針對定義來說的,不是針對符號的引用。鏈接器會按照如下規(guī)則處理重復(fù)定義的全局符號: 規(guī)則1:不允許強(qiáng)符號被多次定義,否則鏈接器報(bào)符號重定義錯(cuò)誤。 規(guī)則2:如果一個(gè)符號在某個(gè)目標(biāo)文件中是強(qiáng)符號,在其它文件中都是弱符號,那么選擇強(qiáng)符號。 規(guī)則3:如果弱符號在所有目標(biāo)文件中都是弱符號,那么選擇占用空間最大的一個(gè)。 我們可以通過GCC的__atrribute__((weak))來定義任何一個(gè)強(qiáng)符號為弱符號,如: __atrribute__((weak)) weak = 1; 鏈接時(shí)如果未找到某個(gè)符號的定義,鏈接器就會報(bào)符號未定義錯(cuò)誤,這種被稱為強(qiáng)引用。與之對應(yīng)的還有一種弱引用,如果弱引用的符號未定義,鏈接器對該引用不報(bào)錯(cuò)。我們可以使用GCC中的__attribute__((weakref))這個(gè)關(guān)鍵字來聲明對一個(gè)外部函數(shù)的引用為弱引用,如: __attribute__((weakref)) void foo(); int main() { if (foo) foo(); } 這種弱符號和弱引用對庫來說十分有用,比如庫中定義的弱符號可以被用戶定位的強(qiáng)符號所覆蓋,從而使程序使用自定義版本的庫函數(shù);或者程序可以對某些擴(kuò)展功能模塊的引用定義為弱引用,如果我們?nèi)サ袅四承┕δ苣K,那么程序也可以正常鏈接,只是缺少了相應(yīng)的功能,這使得程序功能更容易裁剪和組合。 全局符號介入在動態(tài)鏈接中,鏈接器按照各個(gè)模塊之間的依賴關(guān)系,對各個(gè)共享對象進(jìn)行裝載并且將它們的符號并入到全局符號表時(shí),如果兩個(gè)不同的模塊定義了同一個(gè)符號,會出現(xiàn)什么結(jié)果呢?這個(gè)問題涉及到共享對象全局對象介入,即一個(gè)共享對象里面的全局對象會被另一個(gè)共享對象的同名全局符號覆蓋。Linux下的動態(tài)鏈接器的處理規(guī)則是這樣的:當(dāng)一個(gè)符號需要被加入全局符號表時(shí),如果相同的符號名已經(jīng)存在,則后加入的符號被忽略。 共享庫版本Linux使用共享庫版本的方法來解決共享庫的兼容性問題,它規(guī)定共享庫的文件命名規(guī)則如下: libname.so.x.y.z x表示主版本號,主版本號表示庫的重大升級,不同主版本號之間是不兼容的。 y表示次版本號,次版本號表示庫的增量升級,即新增一些新的接口符號,且保持原來的符號不變。在主版本號相同的情況下,高的此版本號的庫向下兼容低的次版本號的庫。 z表示發(fā)布版本號,發(fā)布版本號表示庫的一些錯(cuò)誤修正、性能改進(jìn)等,并不添加任何新的接口,也不對接口進(jìn)行更改。相同主版本號、次版本號的共享庫之間完全兼容。 Linux采用一種叫做SO-NAME的命令機(jī)制來記錄共享庫的依賴關(guān)系。每個(gè)共享庫都有一個(gè)對應(yīng)的SO-NAME,這個(gè)SO-NAME即共享庫的文件名去掉次版本號和發(fā)布版本號,保留主版本號。比如一個(gè)共享庫叫做libfoo.so.2.6.1,那么它的SO-NAME就是libfoo.so.2。系統(tǒng)會為每個(gè)共享庫在它所在的目錄創(chuàng)建一個(gè)跟SO-NAME相同的并且指向它的軟鏈接,這個(gè)軟鏈接會指向目錄中主版本號相同、次版本號和發(fā)布版本號最新的共享庫。 在編譯輸出ELF文件時(shí),將被依賴共享庫的SO-NAME保存到.dynamic中,這樣當(dāng)動態(tài)鏈接器進(jìn)行共享庫依賴文件查找時(shí),就會根據(jù)系統(tǒng)中各種共享目錄中的 SO-NAME軟鏈接自動定向到所兼容的最新版本的共享庫。 |
|