目录
1. 前言
2. __attribute__介绍
3. 测试代码
4. 总结
1. 前言
最近看代码,有个函数根本就没被任何函数调用,但从程序运行结果来看,该函数是被调用了的,找很久都没找到哪里调用了,最后发现该函数前面用__attribute__((constructor))修饰,如下:
__attribute__((constructor)) void load_file()
{
printf("Constructor is called.\n");
g_count = (int *)malloc(sizeof(int));
}
2. __attribute__介绍
__attribute__
可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。__attribute__前后都有两个下划线,并且后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数。
__attribute__语法格式为:__attribute__ ( ( attribute-list ) ) 函数定义
如果函数被设定为constructor属性,则该函数会在main()函数执行之前被自动的执行;若函数被设定为destructor属性,则该函数会在main()函数执行之后或者exit()被调用后被自动的执行。
3. 测试代码
#include <stdio.h>
__attribute__((constructor)) void load_file()
{
printf("Constructor is called.\n");
}
__attribute__((constructor(100))) void load_file1()
{
printf("Constructor 100 is called.\n");
}
__attribute__((constructor(102))) void load_file2()
{
printf("Constructor 102 is called.\n");
}
__attribute__((constructor(99))) void load_file3()
{
printf("Constructor 99 is called.\n");
}
__attribute__((destructor)) void unload_file()
{
printf("destructor is called.\n");
}
int main(int argc, char **argv)
{
printf("this is function %s\n", __func__);
return 0;
}
执行结果如下:
只有constructor有优先级,指定优先级时,先执行优先级小的,再执行优先级大的,最后执行没有指定优先级。0-100是保留优先级。
另外在升级接口时,希望用户使用新接口,而不希望用户再使用原来的旧接口,可以利用类似如下的机制提示用户,当用户在自己的项目使用旧接口时,编译器就会发出警告,提示旧接口已经废弃:
__attribute__((deprecated("该方法已废弃,不建议使用"))) void load_file4()
{
}
int main(int argc, char **argv)
{
load_file4();
return 0;
}
4. 总结
- attribute((constructor)) 先于main()函数调用,attribute((destructor)) 在main()函数后调用
- 只有constructor有优先级,指定优先级时,先执行优先级小的,再执行优先级大的,最后执行没有指定优先级。0-100是保留优先级。
- 可以利用attribute和deprecated对不建议使用或废弃的接口进行说明。
注意:attribute((constructor)) 、attribute((destructor))功能仅仅适用于GNU的gcc编译器,在 MSVC编译器中使用会编译报错,提示不支持。
参考链接:
【1】:https://blog.csdn.net/m0_51139226/article/details/126457719
【2】:https://cloud.tencent.com/developer/article/2008172