给定以下源代码:

#include <stddef.h>
#include <sys/types.h>
#include <dirent.h>

static inline void closedirp(DIR **p) {
    if (*p)
        closedir(*p);
}

#define auto_cleanup(resource) _Generic((resource),     \
    DIR **: closedirp,                  \
        )(resource)

int main() {
#ifdef GENERIC
    __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL;
    t2 = opendir("/tmp");
#else
    __attribute__((cleanup(closedirp))) DIR * t1 = NULL;
    t1 = opendir("/tmp");
#endif
}

它编译和运行时没有泄漏,没有定义。但是,当定义泛型时,编译将失败:
$ gcc foo.c -DGENERIC
foo.c: In function ‘main’:
foo.c:16:2: error: cleanup argument not a function
  __attribute__((cleanup(auto_cleanup))) DIR * t2 = NULL;
  ^

这对泛型的使用是毫无意义的,但是我想扩展它并处理许多类型的资源来自动清理。

最佳答案

_Generic不是函数,而是启动主表达式的关键字。
但在这里,你似乎更是走错了方向:auto_cleanup是一个宏。类似于宏的函数有一个特殊性,即如果在它之后没有()提交,它们就不会被扩展。在这里,您只需将标识符auto_cleanup保留在编译的稍后阶段。但是这个标识符在后面的阶段没有声明为任何东西。
总结一下:
如果使用正确,宏将在编译的早期阶段被文本替换
随后的阶段会看到一个_Generic表达,并决定该_Generic表达的哪个分支
只有那个分支才能“存活”并在代码的那个部分编译
在所有这一切中,没有任何函数或函数指针可用于gcc的cleanup扩展。

10-04 21:59
查看更多