我认为,至少在某些情况下,GCC扩展名 __attribute__((cleanup)) 是个好主意,但我不知道如何以一种好的方式使用它。我所做的一切看起来仍然很烦人。

我看到很多代码只是为了减少键入而做#define _cleanup_(x) __attribute__((cleanup(x)),但是有一种方法可以传递诸如freeclosedirfclose等标准函数?

如我所见,我不能只写:

__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/

10-11 03:03