__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");
}
main.c //
#include <stdio.h>
extern void real_func();
void main()
{
real_func();
}
如果
gcc main.c -lstrong -lweak
那麼輸出結果"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 weak.o strong.o
那麼輸出結果都是"real func"。
所以,如果在so中使用weak屬性,那麼任何不符合預期的情況,都是可能出現的。
官方解釋:
https://sourceware.org/bugzilla/show_bug.cgi?id=3946