首页 > 代码库 > gcc attribute weak & alias应用

gcc attribute weak & alias应用

1          gcc attribute weak & alias应用

alias ("target")

The alias attribute causesthe declaration to be emitted as an alias for another symbol, which must bespecified. For instance,

         void __f () { /* Do something. */; }

         void f () __attribute__ ((weak, alias ("__f")));

defines ‘f’ to be a weakalias for ‘__f’. In C++, the mangled name for the target must be used. It is an error if‘__f’ is not definedin the same translation unit.

Not all targetmachines support this attribute. 

这段来自GCC官方文档的说明,其实讲了gcc的alias和weak attribute。

1.1        gcc weak attribute

具体语法,大概和一般gcc属性一样,需要用到__attribtes__((weak))这样的格式。现在我们通过一个例子来说明一下。

1 我们在weak_symbol.c这个文件中声明了一个common_print函数,并且将此函数声明为__attribute__((weak));同时提供了此函数的定义。

//weak_symbol.c
#include<stdio.h> 
voidcommon_print(const char *s) __attribute__((weak));//有weak声明
voidcommon_print(const char *s)
{
    printf("common_print : %s\n",s);
}

2 在strong_symbol.c这个文件也定义了common_print函数,需要注意的是此函数在两个不同的c文件中声明、定义的原型都一样的。

//strong_symbol.c
#include<stdio.h>
 
voidcommon_print(const char *s) //没有weak声明
{
    printf("application common_print : %s\n",s);
}  
int main(intargc, char *argv[])
{
    common_print("I want to test gcc weakattribute");
    return 0;
}

3 编译连接连个c文件,并且执行的结果如下:

root@VM-Ubuntu203001:/home/test/gcc_test#./test_weak

applicationcommon_print : I want to test gcc weak attribute

 

分析:

1)      首先,同样的原型的两个函数在连个不同的c文件中都有定义,把这两个c文件编译、连接在一起,也没有什么错误。原因就是因为,gcc中有一个strong symbol和weak symbol的概念。默认函数定义都是strong symbol的,两个相同的strong symbol连接在一起,肯定会产生”symbol重复定义”的错误。

但是,这里我们将weak_symbol.c中的common_print加了weak属性,这样gcc再选择的时候优先选择strong symbol

2)      其次,根据例子程序执行的结果来看,执行了strong_symbol.c中的common_print函数。如果我们在strong_symbol.c中不提供common_print函数的实现,那么调用的就是weak_symbol.c中的实现。

3)      由上,我们可以想象,当要用c语音提供一个api库的时候,我们可以把这些api都声明为weak属性的,我们可以提供default实现。当用户想要自己定制的时候,也就很容易实现了。glibc中的很多api就是这样设计的。

1.2        gcc weak &alias attribute配合应用的场景

同样,先看一个例子。

1 我们在weak_symbol.c中提供了一个__lib_print函数的实现,同时声明了print_aprint_b两个函数,但是和上面不通的是,这两个函数增加了__attribute__((weak,alias("__lib_print")))熟悉,即print_aprint_b都是__lib_print的别名(alias)。

//weak_symbol.c
#include <stdio.h>
 
void __lib_print(const char *s)
{
   printf("__lib_print : %s\n", s);
}
 
void print_a(const char *s) __attribute__((weak, alias("__lib_print")));
void print_b(const char *s) __attribute__((weak, alias("__lib_print")));
2 我们在strong_symbol.c中为print_b重新提供了实现,print_a保持默认不变。

//strong_symbol.c
#include <stdio.h>
 
void print_b(const char *s)
{
   printf("application print_b : %s\n", s);
}
int main(int argc, char *argv[])
{
   print_a("I want to test weak&&alias");
   print_b("I want to test weak&&alias");
 
   return 0;
}
3  编译连接连个c文件,并且执行的结果如下:

root@VM-Ubuntu203001:/hometest/gcc_test#./test_weak

__lib_print : I want to testweak&&alias

application print_b : I want to testweak&&alias

分析:

   从执行结果来看,print_a执行的是weak_symbol.c中的__lib_print的实现。print_b执行的是strong_symbol.c中的print_b实现。这个执行结果,我们是应该猜到的,需要说明一点是alias属性可以为一个函数提供很多不同的别名。这样,当我们提供api库的时候,如果多个api有相同的default实现,就可以通过alias机制提供一个default 实现。