转换为void并不能删除warn_unused_result错误。

时间:2021-07-15 22:58:55

In a test, I'm discarding anything from stderr since it clutters the output of the test case. I'm using the following code:

在测试中,我从stderr中丢弃任何东西,因为它包含测试用例的输出。我使用以下代码:

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

When compiling with -Wall -Werror, I get the error

当用-Wall -Werror编译时,我得到了错误。

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

which is expected. However, the usual solution of casting to void doesn't seem to work. That is, changing the code to

这是预期。然而,通常的解决方案是无效的。也就是说,将代码更改为。

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

still produces the same warning. I don't care if this function fails since the worst case scenario is a bit of extra output. Any other way I can fix this?

仍然产生同样的警告。我不关心这个函数是否失败,因为最坏的情况是额外的输出。还有别的办法吗?

EDIT: I know I could introduce an extra unnecessary variable. I would really like to know why casting to void doesn't work.

编辑:我知道我可以引入一个额外的不必要的变量。我真的很想知道为什么选择void无效。

UPDATE: I decided to go with this:

更新:我决定这样做:

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

After reading the freopen documentation more carefully, I see that if opening /dev/null fails, stderr will still be destroyed. This solves that problem.

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

4 个解决方案

#1


6  

Why not simply use the result, as the warning suggests you should.

为什么不直接使用结果呢,就像警告建议的那样。

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

Since the function is declared with the 'warn_unused_result' attribute, you will get the warning unless you use the return value. Since the function either returns null on failure or the file stream argument on success, you might think about assigning the result. However, you should not assign to stderr like that (see below), so this is a bad idea:

由于函数是用“warn_unused_result”属性声明的,除非使用返回值,否则将得到警告。由于函数要么返回null,要么返回成功的文件流参数,您可能会考虑分配结果。但是,您不应该像这样指定stderr(见下面),所以这是个坏主意:

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

Theoretically, you should make that check; there are dire (and implausible) circumstances under which you could fail to open "/dev/null".

理论上,你应该检查;在这种情况下,你可能无法打开“/dev/null”。


Footnote 229 in the C99 standard notes:

C99标准注释的脚注229:

229) The primary use of the freopen function is to change the file associated with a standard text stream (stderr, stdin, or stdout), as those identifiers need not be modifiable lvalues to which the value returned by the fopen function may be assigned.

freopen函数的主要用途是更改与标准文本流相关联的文件(stderr、stdin或stdout),因为这些标识符不需要是可修改的lvalues,而fopen函数返回的值可能会被分配。

Therefore, the assignment is ill-advised. But testing the return value would deal with the compiler warning and might help prevent core dumps too. It is unlikely to improve your code coverage figures, though (the error path is not going be taken very often; it will be hard to force coverage of the error handling).

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

Note that the POSIX description of freopen() has some moderately caustic comments about the design of freopen(), which was invented by the C standard committee (1989 version), presumably without input from POSIX.

注意,freopen()的POSIX描述对freopen()的设计有一些适度的因果性评论,这是由C标准委员会(1989年版本)发明的,假定没有POSIX的输入。

#2


11  

A little heavy on the GCC extensions, but no externally visible variables:

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

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

#3


2  

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

As comments below try

如下评论试试

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

and

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

#4


2  

If you really have to use the C language (not C++) then you may use this workaround:

如果您确实需要使用C语言(而不是c++),那么您可以使用以下方法:

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

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

For example

例如

typedef struct A
{
    int x;
} A;

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

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

#1


6  

Why not simply use the result, as the warning suggests you should.

为什么不直接使用结果呢,就像警告建议的那样。

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

Since the function is declared with the 'warn_unused_result' attribute, you will get the warning unless you use the return value. Since the function either returns null on failure or the file stream argument on success, you might think about assigning the result. However, you should not assign to stderr like that (see below), so this is a bad idea:

由于函数是用“warn_unused_result”属性声明的,除非使用返回值,否则将得到警告。由于函数要么返回null,要么返回成功的文件流参数,您可能会考虑分配结果。但是,您不应该像这样指定stderr(见下面),所以这是个坏主意:

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

Theoretically, you should make that check; there are dire (and implausible) circumstances under which you could fail to open "/dev/null".

理论上,你应该检查;在这种情况下,你可能无法打开“/dev/null”。


Footnote 229 in the C99 standard notes:

C99标准注释的脚注229:

229) The primary use of the freopen function is to change the file associated with a standard text stream (stderr, stdin, or stdout), as those identifiers need not be modifiable lvalues to which the value returned by the fopen function may be assigned.

freopen函数的主要用途是更改与标准文本流相关联的文件(stderr、stdin或stdout),因为这些标识符不需要是可修改的lvalues,而fopen函数返回的值可能会被分配。

Therefore, the assignment is ill-advised. But testing the return value would deal with the compiler warning and might help prevent core dumps too. It is unlikely to improve your code coverage figures, though (the error path is not going be taken very often; it will be hard to force coverage of the error handling).

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

Note that the POSIX description of freopen() has some moderately caustic comments about the design of freopen(), which was invented by the C standard committee (1989 version), presumably without input from POSIX.

注意,freopen()的POSIX描述对freopen()的设计有一些适度的因果性评论,这是由C标准委员会(1989年版本)发明的,假定没有POSIX的输入。

#2


11  

A little heavy on the GCC extensions, but no externally visible variables:

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

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

#3


2  

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

As comments below try

如下评论试试

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

and

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

#4


2  

If you really have to use the C language (not C++) then you may use this workaround:

如果您确实需要使用C语言(而不是c++),那么您可以使用以下方法:

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

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

For example

例如

typedef struct A
{
    int x;
} A;

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

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