現在的位置: 首頁 > 技術文章 > 正文

__attribute__ 之weak,alias屬性

2018年05月30日 技術文章 ⁄ 共 1101字 ⁄ 字號 __attribute__ 之weak,alias屬性已關閉評論

Weak Alias 是 gcc 擴展里的東西,實際上是函數的屬性。這個東西在庫的實現里面可能會經常用到,比如 glibc 里面就用了不少。抄錄一段?gcc 手冊里面的話解釋下函數屬性是干啥的

In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.

先上代碼,看看 weak alias 怎么寫。

第一個文件 dummy.c 內容

int __foo()

{

puts(”I do no thing.”);

}

int foo() __attribute__ ((weak,alias(”__foo”)));

weak 和 alias 分別是兩個屬性。weak 使得 foo 這個符號在目標文件中作為 weak symbol 而不是 global symbol。用 nm 命令查看編譯 dummy.c 生成的目標文件可用看到 foo 是一個 weak symbol,它前面的標記是 W。給函數加上weak屬性時,即使函數沒定義,函數被調用也可以編譯成功。

00000000 T __foo 00000000 W foo U puts

而 alias 則使 foo 是 __foo 的一個別名,__foo 和 foo 必須在同一個編譯單元中定義,否則會編譯出錯。

那么這個東西的用處是?

看第二個文件,func.c,

int foo()

{

puts(”I do something.”);

}

這里有一個函數名字是 foo。如果我們編譯 func.c 和 dummy.c 得到兩個目標文件,當我們同時使用 func.o 和 dummy.o 和其他目標文件進行鏈接時,如果其他目標文件里面引用符號 foo,最終使用到的是 func.c 中定義的函數,而不是 dummy.c中的__foo,雖然它有一個別名 foo。也就是說,我們最終使用到的函數會是“I do something”的那個函數。

當然,單獨使用 dummy.o 鏈接的話使用的是那個“I do no thing”的函數。如果 dummy.o 中的 foo 不是 weak symbol 的話,在鏈接時會產生沖突,這就是我們要使用 weak 的原因。

弱符號:

若兩個或兩個以上全局符號(函數或變量名)名字一樣,而其中之一聲明為weak symbol(弱符號),則這些全局符號不會引發重定義錯誤。鏈接器會忽略弱符號,去使用普通的全局符號來解析所有對這些符號的引用,但當普通的全局符號不可用時,鏈接器會使用弱符號。當有函數或變量名可能被用戶覆蓋時,該函數或變量名可以聲明為一個弱符號。

gnu

二八杠讨论心得
×