最近我遇到了一个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中没有可移植的方式。
幸运的是,这是带有析构函数的C ++的标准功能。
编辑:
MSVC似乎有__try和__finally关键字,也可以用于此目的。这与C ++异常处理不同,我认为它在C中可用。
我认为你会发现清理和try / finally并没有被广泛使用,因为C ++中的隐式支持,它与C“足够接近”,对行为感兴趣的人可以轻松地将代码转换为C ++。
问题的前半部分是可移植的方式。
__attribute__(cleanup)
不是特定于gcc的,它也受到clang和icc的支持,使得msvc成为唯一一个不支持它的主要编译器(而且对于现代C开发来说,这个是无用的)。
因此,即使它不符合ISO标准,它也可以被认为是可移植的,用于大多数实际目的。
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);
}
您可以使用boost :: shared_ptr来实现此目的。
boost::shared_ptr<char> buffer(p, cleanup);