__attribute__((cleanup))

__attribute__((cleanup)) 是 GCC 和 Clang 提供的一个扩展属性,用于在变量超出作用域时自动调用指定的清理函数。它可以简化资源管理,使得在作用域结束时自动释放资源。使用这个属性时,编译器会在生成代码时将清理函数插入到变量作用域的结尾处,从而确保该清理操作会在作用域结束时执行,类似于 C++ 中的析构函数功能。

基本用法

#include <stdio.h>

void cleanup_int(void *p) {
    int *i = (int *)p;
    printf("Cleaning up: %d\n", *i);
}

int main() {
    __attribute__((cleanup(cleanup_int))) int x = 10;
    printf("Value of x: %d\n", x);
    return 0;
}
输出:
Value of x: 10
Cleaning up: 10

在这个示例中,变量 x 在声明时加上了 __attribute__((cleanup(cleanup_int))),因此在 main 函数返回前,编译器会自动插入对 cleanup_int 函数的调用,并将 x 的地址传递给它,从而实现自动清理。

编译器的处理方式

  1. 插入清理代码:编译器会在变量的作用域结束处插入清理函数的调用。即使作用域中包含多条返回路径(如在 ifswitch 语句中提前退出),编译器也会在每条路径上都插入清理函数调用。

  2. 传递指针:清理函数会接受指向变量的指针,这样就能在清理函数中对变量的内容进行访问和处理。

  3. 作用范围__attribute__((cleanup)) 只能用于具有自动存储类型的局部变量,即无法用于全局变量或静态局部变量,因为这些变量的生命周期不受作用域控制。

使用场景

这个属性特别适合用于在 C 中实现 RAII(资源获取即初始化)模式。例如,自动释放内存、文件句柄或锁,避免手动清理的繁琐,减少资源泄漏的风险

注意事项

  • 清理函数应考虑指针为 NULL 的情况。

  • 该特性是编译器的扩展,因此不是标准 C 的一部分,使用时需要确保编译器的兼容性。

Last updated