GCC学習ノート(3)——GCC属性の弱い記号について(weak symbol)


弱い記号の解釈について:
2つ以上のグローバルシンボル(関数または変数名)の名前が同じで、そのうちの1つがweak symbol(弱いシンボル)と宣言されている場合、これらのグローバルシンボルは再定義エラーを起こさない.リンクは弱い記号を無視し、通常のグローバル記号を使用してこれらの記号への参照をすべて解析しますが、通常のグローバル記号が使用できない場合、リンクは弱い記号を使用します.関数または変数名がユーザーによって上書きされる可能性がある場合、関数または変数名は弱い記号として宣言できます.Weakとalias属性が連用されると、弱い別名を宣言することもできます.
使用例:
出典:gcc属性に関するweak
弱いエイリアスの使用例:
//weak.c
#include <stdio.h>
void symbol1()
{
    printf("%s
",__FUNCTION__); } //symbol222.c void symbol222() { printf("%s
",__FUNCTION__); } //void symbol1() __attribute__ ((weak,alias("symbol222"))); // asm() 。 int main() { asm(".weak symbol1
\t .set symbol1, symbol222
\t"); symbol1(); return 0; }

次のコマンドでコンパイル実行するとsymbol 1が出力されます
$ gcc -o weak weak.c symobl222.c
$ ./weak
出力:symbol 1
リンクしないとc、すなわちsymbol 1関数が定義されている場合、symbol 1の代わりにsymbol 1の弱い別名symbol 222が適用される.
次のコマンドでコンパイル実行するとsymbol 222が出力されます.
$ gcc -o weak symbol222.c
$ ./weak
出力:symbol 222
弱い記号の例:
//weak2.c
#include <stdio.h>
extern void symbol1() __attribute__((weak));
void symbol1()
{
    printf("%s.%s
",__FILE__,__FUNCTION__); } int main() { //asm(".weak symbol1
\t .set symbol1, symbol222
\t"); symbol1(); return 0; } //strong.c #include <stdio.h> void symbol1() { printf("%s.%s
",__FILE__,__FUNCTION__); }

コンパイル実行:
リンクstrongをコンパイルしない場合c時:
$ gcc -o weakstrong weak2.c
$ ./weakstrong
出力:weak 2.c symbol1
リンクstrong.cの場合はstrong.cの強い記号symbol 1はweak 2に代わる.cの弱い記号symbol 1:
$ gcc -o weakstrong weak2.c strong.c
$ ./weakstrong
出力:strong.c symbol1
2つの関数が同じ名前の場合、弱い記号の代わりに強い記号(グローバル記号とも呼ばれる)が使用されます.