我认为,至少在某些情况下,GCC扩展名 __attribute__((cleanup))
是个好主意,但我不知道如何以一种好的方式使用它。我所做的一切看起来仍然很烦人。
我看到很多代码只是为了减少键入而做#define _cleanup_(x) __attribute__((cleanup(x))
,但是有一种方法可以传递诸如free
或closedir
,fclose
等标准函数?
如我所见,我不能只写:
__attribute__((cleanup(free))) char *foo = malloc(10);
因为清理回调将接收
char**
指针,所以我必须始终编写如下内容:static void free_char(char **ptr) { free(*ptr); }
__cleanup__((free_char)) char *foo = malloc(10);
这很烦人,最烦人的部分是为所需的所有类型定义此类清理函数,因为显然您不能只为
void **
定义它。避免这些事情的最佳方法是什么? 最佳答案
这里有一个库在unique_ptr
的顶部构建通用智能指针(shared_ptr
和__attribute__((cleanup))
):https://github.com/Snaipe/libcsptr
它允许您编写这样的高级代码:
#include <stdio.h>
#include <csptr/smart_ptr.h>
#include <csptr/array.h>
void print_int(void *ptr, void *meta) {
(void) meta;
// ptr points to the current element
// meta points to the array metadata (global to the array), if any.
printf("%d\n", *(int*) ptr);
}
int main(void) {
// Destructors for array types are run on every element of the
// array before destruction.
smart int *ints = unique_ptr(int[5], {5, 4, 3, 2, 1}, print_int);
// ints == {5, 4, 3, 2, 1}
// Smart arrays are length-aware
for (size_t i = 0; i < array_length(ints); ++i) {
ints[i] = i + 1;
}
// ints == {1, 2, 3, 4, 5}
return 0;
}
至于惯用的,虽然?上面的内容肯定接近惯用的C++。不是C。显然,GCC和Clang主要支持该功能,因为它们也具有C++编译器,因此它们可以选择在C前端中使用RAII机制,而无需支付额外费用。这样编写C-intended-as-C并不是一个好主意。尽管实际上没有使用,但它仍然依赖于存在的C++编译器。
如果是我,我可能会研究实现自动发布池,或者可以在语言级别用纯C实际完成的类似操作。取决于您需要多长时间才能释放资源;为了记忆,您通常可以生活而无需立即清理。
关于c - 一种使用GCC和clang __attribute __((cleanup))和指针声明的好方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34574933/