strong_alias、weak_alias
在阅读glibc源码的时候,遇见了几个没见过的宏
因为我比较好奇,所以特地去找了一下有关这些宏的定义(主要也是想多学一点)
在include/libc-symbols.h中,有我想要了解的两个宏:strong_alias、weak_aliasd的定义
#ifndef __ASSEMBLER__
/* GCC understands weak symbols and aliases; use its interface where
possible, instead of embedded assembly language. */
/* Define ALIASNAME as a strong alias for NAME. */
#define strong_alias(name, aliasname) _strong_alias(name, aliasname)
#define _strong_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((alias (#name))) \
__attribute_copy__ (name);
/* Define ALIASNAME as a weak alias for NAME.
If weak aliases are not available, this defines a strong alias. */
#define weak_alias(name, aliasname) _weak_alias (name, aliasname)
#define _weak_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \
__attribute_copy__ (name);
这里涉及了这些东西:
extern关键字__typeof__attribute__((alias(name)))__attribute_copy__(name)
extern关键倒没什么好说的
__typeof是标准C的扩展,GNU C提供的一种特性
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
看名字就能看得懂typeof什么意思
同样的,__attribute__也是GNU C的一个特性
它能设置函数属性、变量属性、类型属性
其中的alias,在官方的说明页里面,描述如下:
The
aliasattribute causes the declaration to be emitted as an alias for another symbol, which must be specified.
例如,
void __f() {}
void f() __attribute__((alias("__f")));
意思就是,f是函数__f的别名
而__attribute_copy__,我在网上并没有搜到对应的解释
在文件中找到这一行
#ifndef __attribute_copy__
/* Provide an empty definition when cdefs.h is not included. */
#define __attribute_copy__(arg)
#endif
所以去cdefs.h这个文件里面去看看
vim里面提供了丰富的功能,其中就包含多屏功能
https://blog.csdn.net/shuangde800/article/details/11430659
使用:vs开两个屏幕,使用Ctrl+w再加上hjkl在窗口间进行游走
使用:e file来打开新的文件
cdefs.h放在./misc/sys/cdefs.h里
找到对应的文本:
/* Undefine (also defined in libc-symbols.h). */
#undef __attribute_copy__
#if __GNUC_PREREQ (9, 0)
/* Copies attributes from the declaration or type referenced by
the argument. */
# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg)))
#else
# define __attribute_copy__(arg)
#endif
它的解释是:从参数引用的声明或类型复制属性。
遗憾的是,我真的没有找到__copy__的解释
而且,这个东西,看起来也不重要的样子
那么就先忽略掉
所以,strong alias我们就剖析好了
它的用途就是给函数器一个强符号的别名
所谓强符号和弱符号,在这篇博文中有详细的介绍
https://blog.csdn.net/weixin_43839785/article/details/109412754
符号链接原理:链接器发现同时存在弱符号和强符号,优先选择强符号,如果发现不存在强符号,只存在弱符号,则选择弱符号
当程序要使用某个函数,但是不知道其他人有没有定义的时候,就可以使用弱符号取别名
例如,当文件A中定义了函数a,而文件B中要使用函数a,但是它不知道a这个函数是否存在,则,使用弱符号取函数b的别名为a
若A中定义了函数a,则最后的执行结果为a,否则,为b
在标准库中,使用弱符号链接的目的是,防止用户定义重名的函数
例如,在test1.c中定义:
#include <stdio.h>
void open()
{
printf("It is the right open\n");
}
在test2.c中定义
#include <stdio.h>
void open()
{
printf("It is a fake open");
}
int main()
{
open();
return 0;
}
最后编译都过不去,理由是multiple definition of open
在test3.c中加入如下代码:
#include <stdio.h>
#define weak_alias(name, aliasname) \
extern typeof(name) aliasname __attribute__((weak, alias(#name)));
void __open()
{
printf("It is the right open\n");
}
weak_alias(__open, open)
成功编译,运行出来的结果是:
It is a fake open
这就允许了和全局函数或者变量同名的局部函数或者变量的存在。
这里除了weak_alias的定义外,还有一个定义叫weak_hidden_alias
/* Same as WEAK_ALIAS, but mark symbol as hidden. */
#define weak_hidden_alias(name, aliasname) \
_weak_hidden_alias (name, aliasname)
#define _weak_hidden_alias(name, aliasname) \
extern __typeof (name) aliasname \
__attribute__ ((weak, alias (#name), __visibility__ ("hidden"))) \
__attribute_copy__ (name);
这里有一个__visibility__,它的定义同样在
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Function-Attributes.html#Function-Attributes
This attribute affects the linkage of the declaration to which it is attached. There are four supported visibility_type values: default, hidden, protected or internal visibility.
其中,default表示,使用默认的可见性,在ELF中,默认的可见性表示,一个声明对其他模块是可见的
而在动态链接库中,这意味着该定义可能会被覆盖
而hidden表示,如果具有该属性的对象的两个声明在同一个共享库中,则引用同一个对象
https://blog.51cto.com/liulixiaoyao/814329
试想这样子的场景:
程序调用函数A,它存在于两个链接库,那么,程序执行应当引用哪个链接库中的函数?
答案是这取决于链接时的顺序
这里的调用严重依赖于链接库加载的顺序,肯定不可以是一种好的设计
而使用了__attribute__((__visibility__("hidden")))的话,对于链接该库的程序来说,该函数就是不可见的,除非强制声明
即,该接口是不对外暴露的,只是内部使用的
除了default和hidden之外,还有protect和internal