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関連付けられたファイルを変更することです。これらの識別子は、関数によって返される値が割り当てられる変更可能な左辺値である必要はありません。stderrstdinstdoutfopen

したがって、割り当てはお勧めできません。ただし、戻り値をテストすると、コンパイラの警告が処理され、コア ダンプの防止にも役立つ場合があります。ただし、コード カバレッジの数値が改善される可能性は低いです (エラー パスはあまり頻繁には使用されません。エラー処理のカバレッジを強制するのは難しいでしょう)。

の POSIX 記述には、おそらく POSIX からの入力なしで、C 標準委員会 (1989 年版) によって考案されたfreopen()の設計に関する適度に苛烈なコメントが含まれていることに注意してください。freopen()

于 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 に答える