弱符號__attribute__((weak))


弱符號是什么?

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

attribute((weak))的作用

情況是這樣的,碰到一個棘手的問題:我們不確定外部模塊是否提供一個函數func,但是我們不得不用這個函數,即自己模塊的代碼必須用到func函數:

extern int func(void);
...................
int a = func();
if( a > .....)
{
    ..........
}
............

我們不知道func函數是否被定義了;
這會導致2個結果:

1:外部存在這個函數func,並且EXPORT_SYMBOL(func),那么在我自己的模塊使用這個函數func,正確。

2:外部其實不存在這個函數,那么我們使用func,程序直接崩潰。

所以這個時候,__attribute__((weak)) 派上了用場。

在自己的模塊中定義:

int  __attribute__((weak))  func(......)
{
    return 0;
}

將本模塊的func轉成弱符號類型,如果遇到強符號類型(即外部模塊定義了func),那么我們在本模塊執行的func將會是外部模塊定義的func。

如果外部模塊沒有定義,那么,將會調用這個弱符號,也就是在本地定義的func,直接返回了一個1(返回值視具體情況而定)

相當於增加了一個默認函數。

原理:連接器發現同時存在弱符號和強符號,有限選擇強符號,如果發現不存在強符號,只存在弱符號,則選擇弱符號。如果都不存在:靜態鏈接,恭喜,編譯時報錯,動態鏈接:對不起,系統無法啟動。

weak屬性只會在靜態庫(.o .a )中生效,動態庫(.so)中不會生效。

強符號和弱符號的例子

舉個例子:
strong.c //生成 libstrong.so

#include <stdio.h>
void real_func()
{
	printf("int real func\n");
}

weak.c //生成libweak.so

#include <stdio.h>
void real_func() __attribute__((weak));
void real_func()
{
	printf("fake func\n");
}

如果

gcc main.c -lstrong -lweak

那么輸出結果"real func"。

main.c

#include <stdio.h>
extern void real_func();
void main()
{
        real_func();
}

如果

gcc main.c -lweak -lstrong

那么輸出結果為"fake func"。

可見,對於動態庫,weak屬性毫無作用,且main中調用哪個real_func(),取決於順序。

如果將strong.c 和 weak.c編譯成.a或者.o

gcc main.c strong.o weak.o

或者

gcc main.c strong.o weak.o

那么輸出結果都是"real func"。

所以,如果在so中使用weak屬性,那么任何不符合預期的情況,都是可能出現的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM