弱符號

弱符號

弱符號表示在連結執行檔和可連結格式(ELF)對象檔案期間特別注釋的符號。默認情況下,沒有任何注釋,目標檔案中的符號很強。 在連結期間,強符號可以覆蓋同名的弱符號。相反,共享名稱的兩個強符號在連結時產生連結錯誤。 連結二進制執行檔時,弱聲明的符號不需要定義。相比之下,(默認情況下)沒有定義的聲明的強符號會觸發未定義的符號連結錯誤。 C或C ++語言標準沒有提到弱符號;因此,將它們插入代碼並不是非常便攜。 即使兩個平台支持用於將符號標記為弱的相同或類似語法,語義也可能在細微點上不同,例如, 動態連結期間弱符號是否會失去語義。

語法

GNU編譯器集合和Solaris Studio C編譯器共享相同的語法,用於將符號注釋為弱,即特殊的#pragma,#pragma weak,以及函式和變數屬性__attribute __((weak))。

編譯

屬性

支持平台

nm命令標識目標檔案,庫和執行檔中的弱符號。 在Linux上,如果弱默認定義可用,則弱函式符號標記為“W”,如果不可用,則標記為“w”。 弱定義的變數符號標有“V”和“v”。 在Solaris上,“nm”為弱符號列印“WEAK”而不是“GLOB”。

實例

靜態實例

main.c:

power_slow.h:

power_slow.c:

power.c:

Build commands:

輸出

刪除weak屬性並重新執行build命令時,最後一個失敗並顯示以下錯誤訊息(在Linux上):

倒數第二個仍然成功,而./slow具有相同的輸出。

共享實例

從前面的例子中取main.c並添加:

用以下內容替換power_slow.c:

構建命令:

輸出

刪除weak屬性並重新執行構建命令不會產生構建錯誤,並導致main和main2的輸出(在Linux上)相同。 main3的構建命令導致以下警告和錯誤訊息(在Linux上):

警告由編譯器發出,因為它可以靜態地確定if(user_hook)表達式user_hook總是評估為true,因為它包含ELF跳轉表條目。 錯誤訊息由連結器發出。 main4的構建包含相同的警告但沒有連結錯誤。

套用

弱符號可以用作提供功能的默認實現的機制,其可以在連結時由更專業(例如,最佳化的)替換。 然後將默認實現聲明為弱,並且在某些目標上,具有強聲明符號的目標檔案將添加到連結器命令行。

如果庫將符號定義為弱符號,則連結該庫的程式可以自由地提供強大的符號,例如,用於自定義目的。

弱符號的另一個用例是維護二進制向後兼容性。

相關方法

C預處理器(CPP)條件結構也可用於在符號的不同版本之間切換。 與弱符號的區別在於弱符號由連結器解釋。 CPP在C編譯器之前編譯每個轉換單元期間運行。

構建過程(例如make)可以以條件方式實現,使得僅創建符號的不同版本或者根據目標使用和連結不同(專用)庫。

相關詞條

熱門詞條

聯絡我們