12

在测试中,我会丢弃任何东西,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);

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

编辑:我知道我可以引入一个额外的不必要的变量。我真的很想知道为什么强制转换为 void 不起作用。

更新: 我决定这样做:

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

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

4

4 回答 4

12

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

#define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; })
ignore_result(freopen("/dev/null", "w", stderr));
于 2010-09-01T04:13:42.343 回答
5

为什么不简单地使用结果,正如警告所建议的那样。

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函数的主要用途是更改与标准文本流(、、或)关联的文件stderrstdin因为stdout这些标识符不需要是可修改的左值,fopen函数返回的值可以分配给这些左值。

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

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

于 2010-09-01T04:38:46.563 回答
2
int tossmeout = freopen("/dev/null", "w", stderr);

正如下面的评论尝试

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

(void *)freopen("/dev/null", "w", stderr);
于 2010-09-01T02:52:32.293 回答
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;
}
于 2011-05-09T04:43:03.290 回答