GNU C扩展__attribute __(__ cleanup__)如何工作?

时间:2017-04-12 05:41:23

标签: c gcc gnu

它是否分析变量的生命周期并简单地在正确的位置插入清理函数调用?是否有任何间接费用?

我编写了两段简单的代码来比较性能,并在没有优化的情况下编译它们。

代码1:

#include <stdio.h>
#include <stdlib.h>

void clean_up(int **final_value)
{
    free(*final_value);
}

int main(int argc, char **argv)
{
  for (int i = 0; i < 10000000; i++) { 
    int *avar = malloc(sizeof(int));
    clean_up(&avar);
  }

  return 0;
}

码2:

#include <stdio.h>
#include <stdlib.h>

void clean_up(int **final_value)
{
    free(*final_value);
}

int main(int argc, char **argv)
{
  for (int i = 0; i < 10000000; i++) { 
    int *avar __attribute__ ((__cleanup__(clean_up))) = malloc(sizeof(int));
  }

  return 0;
}

他们的表现非常相似。

2 个答案:

答案 0 :(得分:3)

您最好使用一些优化进行编译,特别是如果您想查看生成的汇编代码(使用gcc -S -fverbose-asm -O编译)

直觉behind __attribute__((cleanup))是GCC实际上是所有C,C ++,Ada,Fortran,Go的编译器....该属性强制使用与C ++相同的内部表示局部变量的析构函数。清理发生在当前块范围的末尾(例如,在块的右括号}处)。因此,编译器正在将您的code2转换为相应的code1。

全局变量或静态变量的析构函数(在main返回后运行)的函数是__attribute__((destructor))函数(对于插件也在dlclose运行)。< / p>

因此,要理解这些属性,最好用C ++术语来思考。

我的观点是,如果你需要这些cleanup属性,你应该用C ++编写你的东西而不是C代码。你的代码将更具可读性并且更少依赖于编译器。我觉得cleanup实际上只对生成的C代码有用。我从来没有使用它(并且觉得当我需要它时,我应该切换到C ++)。

答案 1 :(得分:1)

当变量超出范围时,将调用cleanup函数。它不关心,这是否会留下其他指针悬挂。