2011-12-15 84 views
3

如果我在目標文件和庫中定義了相同的符號,GNU鏈接器將從目標文件中獲取符號。考慮下面這個例子:多個已定義符號的C/C++鏈接器順序

g++ -L"dir/to/lib" -o Executable Test.o foo.o -lMyLib 

如果我在兩個Foo.cpp中和源文件「MyLib中」定義的函數foo具有相同簽名的編譯,GNU鏈接總是喜歡從以前如果一個我使用這個命令。

此行爲是GNU工具鏈特有的嗎?你是否知道其他鏈接器的行爲方式相同?這是隨處可見的(GNU文檔,C++標準)?我找不到任何東西...

我想使用此功能來取代/模擬某些功能,同時進行單元測試(又名鏈接縫)。

+0

目標文件形成可執行文件。這些庫然後用於**解決任何未定義的符號**。因此可執行文件將提供所有主要功能。對於任何未解決的符號,它們來自哪裏將嚴重依賴於MyLib(和其他庫)是靜態還是動態。對於靜態庫,它是很好的定義。對於動態庫,它依賴於運行時動態鏈接器,並且它在每個操作系統上都有所不同。 – 2011-12-15 17:03:30

回答

3

也許吧。

鏈接器如何處理它的文件取決於鏈接器,但在確切的情況下,您已經描述過,我不認爲 是任何變體。當你指定一個目標文件時,它將包括在內的 到你的最終版本中,並且你會得到它定義的任何符號; 如果兩個目標文件定義了相同的符號,則通常會從鏈接程序中獲得一個 錯誤(但由於符號太弱或數據定義類似於Fortran類似,所以也有例外)。庫是對象文件的集合 ;對庫的標準處理是爲連接器 掃描它,併合並任何對象(並且只包含那些對象),其中 定義了一個未定義的外部對象。如果 庫中的目標文件僅定義了有問題的符號,並且其定義 已由顯式指定的目標文件解決,鏈接器 將不會將庫中的目標文件併入程序中。 如果庫中的目標文件也定義了其他符號,然而其中一個解析了其他未定義的外部符號,則該庫中的對象文件 將與其定義的所有符號一起併入您的程序。這可能會導致多個 的定義。

0

由語言的角度看,「連接命令」是未指定的,並且不能在使用可靠的方式。

通過平臺(工具鏈)的立場,它必須以某種方式指定,並且 - 通常 - 它考慮所有符號未解析的所有符號的庫,而不是本地解析的所有符號。 這允許開發人員屏蔽/替換庫函數。

現在,gcc(作爲msvc)以啓動鏈接器的命令行的相同順序鏈接。這種行爲是否可以被「信任」(從某種意義上說,它將在未來的版本中保留下來)並不清楚。 (GCC文檔是用現在的動詞寫的......)

+1

所有的Unix連接器都嚴格按照給定的順序處理文件。這不是** VS的情況; VS一次處理所有的文件,就好像它們被連接在一起(或多或少)。因此,如果在Unix下指定`a.o -lb c.o`,`lib.a`中將不會找到'c.o`的未解析的外部數據;用VS,如果你指定`a.obj b.lib c.obj`,他們會。 – 2011-12-15 16:06:18

相關問題