2013-05-01 67 views
7

我知道編譯時包含在可執行文件中的代碼可以來自對象文件(.o文件)和靜態鏈接庫(.lib/.a文件)。這兩者之間的區別在根本上和概念上是什麼?爲什麼「目標代碼」和「靜態鏈接庫」有不同的概念?每個人有什麼優點和缺點,爲什麼使用一個而不是另一個?靜態鏈接庫可以由目標文件創建,反之亦然,可以使用靜態鏈接庫創建目標文件?C/C++:靜態鏈接庫和目標文件有什麼不同?

回答

6

庫只是一個包含許多目標文件的文件,可以通過搜索來解析符號。因此,通常,當你將對象鏈接在一起時,你可以在一個可執行文件中獲得所有對象(儘管一些優化鏈接器可以拋出未使用的對象)。

當您向鏈接器提供庫時,它會檢查其中的每個對象文件並引入滿足未解決符號所需的那些對象文件(並且可能會繼續將它們帶入,直到所有符號都已解析或無更多可以)。

這只是將大量對象有效打包到單個文件中的一種方式,以便鏈接器可以完成更多的工作 - 您不必擔心需要哪些對象。

如果您想到C庫,您可能有一個printf.o,puts.o, fopen.o作爲保持您的源很好地分開的結果。您不希望用戶必須明確列出他們想要的每個對象文件,以便將所有內容打包到libc.a中,並告訴他們只需要鏈接該單個文件即可。


的靜態鏈接位在這裏無關緊要,它只是決定該對象應該進入鏈接時可執行文件,而不是在運行時被動態加載。這是解釋here

+1

那麼爲什麼在使用庫文件而不是一個或多個目標文件時,用戶必須執行的工作效率或工作量有什麼不同?鏈接器不能總是優化嗎?如果靜態鏈接庫是對象文件的集合,那麼它是否將所有對象子文件全部加載或不加載,還是僅使用那些已被使用的符號?您是否有一個例子,說明如何根據代碼是否來自靜態鏈接庫或目標文件,從相同的代碼創建可執行文件,從而產生重大差異? – user553702 2013-05-01 07:02:35

+1

@ user553702,你想不得不列出85個不同的目標文件,其中有些文件甚至不需要,或者你想只列出'libc.a'並讓鏈接器解決它?也許我天生懶惰,但這並不總是_bad_的事情:-)至於鏈接器如何工作,它可以拋棄那些即使明確列出它們也不會滿足任何符號的東西。大多數人不會通過IST​​R Visual Studio那樣聰明。 – paxdiablo 2013-05-01 07:05:11

+0

爲簡單起見,大多數鏈接程序僅從庫中提取它們需要的目標文件(以及它們決定需要的每個目標文件的_all_)。 – paxdiablo 2013-05-01 07:07:38

9

目標文件是已編譯但未鏈接的代碼。庫包含對象文件。因此你的問題就變成了:「如果我只能使用目標文件,爲什麼要使用靜態鏈接的庫?」這是爲什麼。

不同對象的集合,每個都有自己的符號表,庫有單一的,統一符號表,當ar通過使用s開關庫開發人員創建名爲。 s調用ranlib爲該存檔中的所有對象創建統一的符號表。

運行殼ranlib顯示幫助文本的第一行:

生成索引,以加快存取檔案。

而且從通用ranlib docs

具有這種索引的存檔可以加速鏈接庫和 允許庫中的程序,而不考慮叫對方 其放置在歸檔。T

另請參見FreeBSD ranlib docs - 不同的措詞,相同的想法:聯動的速度。