代码之家  ›  专栏  ›  技术社区  ›  Michael Mior Aouidane Med Amine

强制转换为void不会删除warn_unused_result错误

  •  12
  • Michael Mior Aouidane Med Amine  · 技术社区  · 15 年前

    在测试中,我放弃了 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 失败, 标准错误 仍将被摧毁。这就解决了这个问题。

    4 回复  |  直到 13 年前
        1
  •  6
  •   Jonathan Leffler    13 年前

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

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

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

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

    理论上,您应该进行检查;在可怕(和不可信)的情况下,您可能无法打开“/dev/null”。


    C99标准注释中的脚注229:

    229) 的主要用途 freopen 函数用于更改与标准文本流关联的文件 ( stderr , stdin stdout ,因为这些标识符不需要修改值 返回的 fopen 可以分配功能。

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

    注意的posix描述 freopen() FLUPEN() 这是C标准委员会(1989年版)发明的,大概没有来自POSIX的输入。

        2
  •  11
  •   Hugh    15 年前

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

    #define ignore_result(x) ({ typeof(x) z = x; (void)sizeof z; })
    ignore_result(freopen("/dev/null", "w", stderr));
    
        3
  •  2
  •   Jonathan Leffler    15 年前
    int tossmeout = freopen("/dev/null", "w", stderr);
    

    作为下面的评论,请尝试

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

    (void *)freopen("/dev/null", "w", stderr);
    
        4
  •  2
  •   Sergey Shandar Gary Liu    15 年前

    如果你真的必须使用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;
    }