当前位置: 首页 > article >正文

【C语言】__attribute__((constructor)) 和 __attribute__((destructor))详细解析

__attribute__((constructor))__attribute__((destructor)) 是 GCC(GNU Compiler Collection)中的两个特殊属性,用于在程序初始化或终止时自动执行特定的函数。它们允许开发者控制函数在程序生命周期中的执行顺序。下面详细介绍其用法及优先级控制的内容:

1. __attribute__((constructor))

  • 定义:当一个函数被标记为 __attribute__((constructor)) 时,该函数会在 main() 函数之前自动执行,即在程序初始化阶段执行。

  • 用法

    #include <stdio.h>
    
    void __attribute__((constructor)) init_function() {
        printf("This function is called before main()\n");
    }
    
    int main() {
        printf("This is inside main()\n");
        return 0;
    }
    

    输出

    This function is called before main()
    This is inside main()
    
  • 优先级控制:可以通过给 constructor 属性传递一个整数参数来设置优先级,数字越小,函数越早执行。默认为 priority = 100,也就是说,所有没有显式设置优先级的 constructor 函数都会按照代码中的出现顺序执行,而设置了优先级的函数则按照从低到高的顺序执行。

    例如:

    #include <stdio.h>
    
    void __attribute__((constructor(101))) first_function() {
        printf("First function\n");
    }
    
    void __attribute__((constructor(102))) second_function() {
        printf("Second function\n");
    }
    
    void __attribute__((constructor(50))) third_function() {
        printf("Third function (highest priority)\n");
    }
    
    int main() {
        printf("This is inside main()\n");
        return 0;
    }
    

    输出

    Third function (highest priority)
    First function
    Second function
    This is inside main()
    

    在这个例子中,third_function 设置了优先级为 50,比其他函数优先级高,因此首先执行。first_functionsecond_function 分别为 101102,它们按照优先级顺序执行。

2. __attribute__((destructor))

  • 定义:与 constructor 相对,__attribute__((destructor)) 标记的函数会在 main() 函数执行结束后自动执行,即程序终止时执行,用于清理资源。

  • 用法

    #include <stdio.h>
    
    void __attribute__((destructor)) cleanup_function() {
        printf("This function is called after main()\n");
    }
    
    int main() {
        printf("This is inside main()\n");
        return 0;
    }
    

    输出

    This is inside main()
    This function is called after main()
    
  • 优先级控制:与 constructor 类似,destructor 也可以通过传递参数控制优先级,数字越小,函数越早执行。默认优先级为 100。这对于确保某些清理操作比其他操作先执行是很有用的。

    例如:

    #include <stdio.h>
    
    void __attribute__((destructor(102))) first_cleanup() {
        printf("First cleanup\n");
    }
    
    void __attribute__((destructor(50))) second_cleanup() {
        printf("Second cleanup (highest priority)\n");
    }
    
    int main() {
        printf("This is inside main()\n");
        return 0;
    }
    

    输出

    This is inside main()
    Second cleanup (highest priority)
    First cleanup
    

    在这里,second_cleanup 由于优先级较高(50),会在 first_cleanup 之前执行。

3. 典型应用场景

  • 资源初始化和清理:通过设置优先级,可以确保程序中依赖于某些资源的初始化函数先于其他函数执行,并且清理函数也可以有序执行。例如:

    • constructor 函数可以用于分配全局资源、初始化库或加载配置。
    • destructor 函数可以用于释放全局资源、保存状态或关闭文件/数据库连接等。
  • 动态链接库中的应用:在动态链接库中,constructordestructor 常用于确保在加载库时初始化全局状态,在卸载库时清理全局资源。

4. 注意事项

  • 不可过度使用:虽然 constructordestructor 属性使得代码的自动执行变得方便,但过多使用可能导致程序的控制流不太清晰,增加维护复杂度。建议仅在资源初始化和清理等明确的场景中使用。

  • 跨平台兼容性:这些属性属于 GCC 扩展,其他编译器(如 MSVC)可能不支持,因此如果需要跨平台兼容,需小心处理。

  • 执行时机constructor 函数的执行时机是在动态链接器完成库的加载后、但在 main() 之前;而 destructor 函数的执行时机是在 main() 或共享库的其他代码完成执行后、在程序终止之前。

5. 总结

  • __attribute__((constructor)):标记的函数在 main() 函数之前执行,适合用于程序初始化。

    • 可以通过设置优先级,控制多个初始化函数的执行顺序,优先级数值越小,函数执行得越早。
  • __attribute__((destructor)):标记的函数在 main() 函数之后、程序终止时执行,适合用于清理资源。

    • 同样可以通过设置优先级,控制多个清理函数的执行顺序,优先级数值越小,函数执行得越早。

http://www.kler.cn/news/316695.html

相关文章:

  • 基于微信小程序的商品展示+ssm(lw+演示+源码+运行)
  • 【论文速看】DL最新进展20240923-长尾综述、人脸防伪、图像分割
  • 非root安装Augustus报错解决
  • 速盾:凡科建站开cdn了吗?
  • C++: 使用红黑树模拟实现STL中的map和set
  • MySQL篇(窗口函数/公用表达式(CTE))(持续更新迭代)
  • “明月寄情,文化共融”iEnglish助力青少年用英语讲述中国故事
  • 【PostgreSQL】PostgreSQL数据库允许其他IP连接到数据库(Windows Linux)
  • 【小六壬占卜代码】
  • STM32的GPIO的八种工作模式
  • 计算机毕业设计 奖学金评定管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • 牛客周赛 Round 60(思维、逆元、组合数、概率DP)
  • 箭头与数字识别系统源码分享
  • STM32F407单片机编程入门(十六) DMA详解及ADC-DMA方式采集含源码
  • 『功能项目』主角属性值显示【75】
  • html+css+js网页设计 旅游 穷游10个页面
  • 【Qt笔记】QTabWidget控件详解
  • 828华为云征文 | 云服务器Flexus X实例,搭建MC我的世界服务器
  • 力扣773:滑动谜题
  • K8s Calico替换为Cilium,以及安装Cilium过程
  • 进阶SpringBoot之集合 Redis
  • html/css怎么禁用浏览器自动填写
  • 使用 Nginx 搭建 Webdav 服务
  • 安全通信网络等保
  • Android OpenGLES2.0开发(二):环境搭建
  • 付费电表系统的通用功能和应用过程参考模型(中)
  • GPT1-GPT3论文理解
  • 关于wordPress中的用户登录注册等问题
  • MySQL函数介绍--日期与时间函数(二)
  • react hooks--useMemo