转换为void不会删除warn_unused_result错误

时间:2010-09-01 02:40:54

标签: c gcc gcc-warning

在测试中,我丢弃stderr中的任何内容,因为它会使测试用例的输出变得混乱。我正在使用以下代码:

freopen("/dev/null", "w", stderr);

使用-Wall -Werror进行编译时,出现错误

error: ignoring return value of ‘freopen’, declared with attribute warn_unused_result

这是预料之中的。但是,通常的void投射解决方案似乎不起作用。也就是说,将代码更改为

(void) freopen("/dev/null", "w", stderr);

仍会产生相同的警告。我不在乎这个函数是否失败,因为最坏的情况是一些额外的输出。还有其他方法可以解决这个问题吗?

编辑:我知道我可以引入额外的不必要变量。我真的很想知道为什么施放到无效是不行的。

更新 我决定这样做:

FILE *null = fopen("/dev/null", "w");
if (null) { fclose(stderr); stderr = null; }

在仔细阅读freopen文档后,我发现如果打开/dev/null失败,stderr仍将被销毁。这解决了这个问题。

4 个答案:

答案 0 :(得分:11)

GCC扩展有点重,但没有外部可见的变量:

#define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; })
ignore_result(freopen("/dev/null", "w", stderr));

答案 1 :(得分:6)

为什么不简单地使用结果,因为警告建议你应该这样做。

if (freopen("/dev/null", "w", stderr) == 0)
    ...oops...lost stderr...hard to report errors...

由于函数是使用'warn_unused_result'属性声明的,因此除非使用返回值,否则将收到警告。由于函数在失败时返回null或在成功时返回文件流参数,因此您可能会考虑分配结果。但是,你不应该 像那样分配给stderr(见下文),所以这是一个坏主意:

stderr = freopen("/dev/null", "w", stderr);

理论上,你应该做那个检查;存在可能无法打开“/ dev / null”的可怕(并且难以置信)的情况。


C99标准中的脚注229注释:

  

229) freopen函数的主要用途是更改与标准文本流关联的文件   (stderrstdinstdout),因为这些标识符不一定是值可修改的左值   可以分配由fopen函数返回的。

因此,这项任务是不明智的。但是测试返回值会处理编译器警告,也可能有助于防止核心转储。但是,它不太可能改善您的代码覆盖率数据(错误路径不会经常使用;很难强制覆盖错误处理)。

请注意freopen()的POSIX描述对freopen()的设计有一些适度的刻薄评论,这是由C标准委员会(1989版)发明的,可能没有来自POSIX的输入。

答案 2 :(得分:2)

int tossmeout = freopen("/dev/null", "w", stderr);

如下面的评论尝试

FILE *tossmeout = freopen("/dev/null", "w", stderr);

(void *)freopen("/dev/null", "w", stderr);

答案 3 :(得分:2)

如果你真的必须使用C语言(而不是C ++),那么你可以使用这个解决方法:

inline void ignore_result_helper(int __attribute__((unused)) dummy, ...)
{
}

#define IGNORE_RESULT(X) ignore_result_helper(0, (X))

例如

typedef struct A
{
    int x;
} A;

__attribute__((warn_unused_result)) A GetA()
{
    A const a;
    return a;
}

int main()
{
    IGNORE_RESULT(GetA());
    return 0;
}