便携式等同于gcc的__attribute __(清理)

问题描述 投票:15回答:5

最近我遇到了一个gcc扩展,我发现它非常有用:__attribute__(cleanup)

基本上,这允许您在退出范围时为局部变量分配清理调用。例如,给定以下代码部分,必须在调用foo的任何和所有情况下显式维护和处理所有内存。

void foo() {
   char * buff = ...; /* some memory allocation */
   char * buff2 = 0, * buff3 = 0;
   if (! buff) {
      return;
   } else {
      buff2 = ...; /* memory allocation */
      if (! buff2) {
         goto clean_exit;
      } else {
         /* ... and so on ... */
      }
   }

clean_exit:
   free (buff);
   free (buff2);
   free (buff3);
}

但是,通过使用可以减少到的扩展名

#define clean_pchar_scope __attribute__((cleanup(pchar_free)))

void pchar_free (char ** c) { free (*c); }

void foo () {
   char * buff clean_pchar_scope = ...; /* some memory allocation */
   char * buff2 clean_pchar_scope = 0, * buff3 clean_pchar_scope = 0;
   if (! buff)
      return;
   buff2 = ...; /* memory allocation */
   if (! buff2)
      return;
   /* and so on */
}

现在,所有内存都在范围的基础上回收,而不使用嵌套的if / else或goto构造以及函数的统一内存释放部分。我意识到goto的使用可以避免使用更多嵌套的if / else结构(所以,请不要对goto进行神圣的战争......)并且这个例子是设计的,但事实仍然是这可能是非常有用的功能。

不幸的是,据我所知,这是特定于gcc的。我对任何便携式方法感兴趣(如果它们存在的话)。有没有人有过使用gcc之外的其他方面的经验?

编辑:似乎可移植性没有发挥作用。考虑到这一点,有没有办法在gcc空间之外做到这一点?似乎很好的功能是gcc特定的......

c gcc garbage-collection scope portability
5个回答
8
投票

在C中没有可移植的方式。

幸运的是,这是带有析构函数的C ++的标准功能。

编辑:

MSVC似乎有__try和__finally关键字,也可以用于此目的。这与C ++异常处理不同,我认为它在C中可用。

我认为你会发现清理和try / finally并没有被广泛使用,因为C ++中的隐式支持,它与C“足够接近”,对行为感兴趣的人可以轻松地将代码转换为C ++。


4
投票

问题的前半部分是可移植的方式。


0
投票

__attribute__(cleanup)不是特定于gcc的,它也受到clang和icc的支持,使得msvc成为唯一一个不支持它的主要编译器(而且对于现代C开发来说,这个是无用的)。

因此,即使它不符合ISO标准,它也可以被认为是可移植的,用于大多数实际目的。


-2
投票
void foo()
{
        char *buf1 = 0, *buf2 = 0, *buf3 = 0;
        /** more resource handle */

        do {

                if ( buf1 = ... , !buf1 ) break;
                if ( buf2 = ... , !buf2 ) break;
                if ( buf3 = ... , !buf3 ) break;

                /** to acquire more resource */

                /** to do with resource */

        } while (0);

        /** to release more resource */

        if (buf3) free(buf3);
        if (buf2) free(buf2);
        if (buf1) free(buf1);
}

-5
投票

您可以使用boost :: shared_ptr来实现此目的。

boost::shared_ptr<char> buffer(p, cleanup);
© www.soinside.com 2019 - 2024. All rights reserved.