2013-03-06 13 views
19

何らかの理由で自分のプログラムで致命的な状況が見つかった場合は、エラーコードを出して終了したいと思います。 場合によっては、致命的なエラーのコンテキストが他のファイル記述子の範囲外です。 これらのファイル記述子を閉じることをお勧めします。 私が知る限り、これらのファイルはプロセスが終了すると自動的に閉じられます。終了時にファイル記述子を閉じるのが良い習慣です

+0

を扱うことができるクローズするルーチン常にクリーンなシャットダウンを実行する可能性があります。後者には、システムが使用しようとしているリソースがまだ解放されていることが含まれます。 – alk

+0

インポートとして、これは明示的に暗黙よりも常に良いと言います! – Kaunteya

+0

@alkこれは複雑なレガシーシステムであり、カスケードエラーは不可能であり、リファクタリングはオプションではありません。 – stdcall

答えて

13

ファイルは自動的に閉じられますが、それは良い方法です。この例で

参照くださいvalgrindの

[email protected]:~$ cat demo.c 
#include <stdio.h> 

int main(void) 
{ 
    FILE *f; 

    f = fopen("demo.c", "r"); 
    return 0; 
} 
[email protected]:~$ valgrind ./demo 
==3959== Memcheck, a memory error detector 
==3959== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. 
==3959== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==3959== Command: ./demo 
==3959== 
==3959== 
==3959== HEAP SUMMARY: 
==3959==  in use at exit: 568 bytes in 1 blocks 
==3959== total heap usage: 1 allocs, 0 frees, 568 bytes allocated 
==3959== 
==3959== LEAK SUMMARY: 
==3959== definitely lost: 0 bytes in 0 blocks 
==3959== indirectly lost: 0 bytes in 0 blocks 
==3959==  possibly lost: 0 bytes in 0 blocks 
==3959== still reachable: 568 bytes in 1 blocks 
==3959==   suppressed: 0 bytes in 0 blocks 
==3959== Rerun with --leak-check=full to see details of leaked memory 
==3959== 
==3959== For counts of detected and suppressed errors, rerun with: -v 
==3959== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 

あなたが見ることができるように、それはメモリはあなたがatexit()を利用することができ、いくつかの状況では

をリーク発生します

#include <stdio.h> 
#include <stdlib.h> 

static FILE *f; 

static void free_all(void) 
{ 
    fclose(f); 
} 

static int check(void) 
{ 
    return 0; 
} 

int main(void) 
{ 
    atexit(free_all); 
    f = fopen("demo.c", "r"); 
    if (!check()) exit(EXIT_FAILURE); 
    /* more code */ 
    return 0; 
} 
+4

'fopen()'によって返される 'FILE'ポインタはファイル記述子ではありません。関連するバッファを持つファイルストリームです。だからあなたのプログラムが適切な 'fclose()'コールなしで 'main'から返ってくると、valgrindが示すように、このメモリはリークしたままになります。 _file記述子に関する質問には未回答のままです。 –

+2

@PavelZhuravlev ops、そうです、申し訳ありません –

5

私が知る限り、これらのファイルはプロセスが終了すると自動的に閉じられます。

これに頼らないでください。概念的には、プロセスが終了するとあなたの責任割り当てられたメモリを解放し、非標準のファイルディスクリプタを閉じます。もちろん、すべての正常なOS(Windowsも)は処理後にクリーンアップしますが、期待する。

3

はい。メインプログラムが別のプログラムのクラスになったとします。これで、リソースリークについて説明しました。あなたは基本的にプロセスの状態であるグローバルプログラム状態に依存してカプセル化に違反しています。モジュールではなく、クラスではなく、スレッドではなくADTではなく、プロセス全体がシャットダウン状態にあります。

0

OSがあなたが残した混乱について何かをすることは、C言語で保証されていません。これはプログラミング標準の範囲外です。 Cは暗黙のうちに、あなたがしなければならないようにすべての標準クリーンアップ関数(malloc fcloseなど)を呼び出すと仮定しています。

したがって、すべてOSによって異なります。あなたの質問は特定のOSに対応していないので、答えられません。現在、主要な商用デスクトップOSはすべてクリーンアップを行っていますが、それは厄介なプログラミングを練習するための言い訳ではありません。

あなたのプログラムはOSプロセス/実行可能ファイルと同じではないが、スレッド、Windows DLL、ドライバなどで構成され、親プロセスと同じメモリスペースに存在するとします。その後、リソースを漏らし、親からメモリを盗みます。

6

POSIXプログラミング「UNIX環境での高度なプログラミング」への古典的なガイドは述べて:

プロセスが終了すると、その開いているファイルのすべてがカーネルによって自動的に閉じられています。多くのプログラムがこの事実を利用しており、明示的にファイルを閉じることはありません。

あなたの質問にOSについては言及しなかったが、このような行動は、どのOSから期待されなければなりません。プログラムの制御フローがexit()またはreturnからmain()に変わるたびに、処理後のクリーンアップはシステムの責任となります。

OSの実装にバグが発生する可能性が常にあります。一方、プロセス終了時には、実行可能ファイルイメージ、スタック、プロセスに関連するカーネルオブジェクトによって占有されているメモリよりも、いくつかのオープンファイル記述子よりも多くの方法の割り当てを解除する必要があります。この動作をユーザー空間から制御することはできません。意図したとおりに動作するだけで動作します。ですから、なぜプログラマはfdの自動クローズに頼ることができませんか?

したがって、fdを開いたままにする唯一の問題は、プログラミングスタイルの質問になる可能性があります。また、stdioオブジェクト(システム提供のファイルI/Oの周りに構築されたもの)を使用した場合のように、バレルグラインド中にアラートが混乱することがあります。システムリソースが漏洩する危険性については、OSの実装が実際にはバグでない限り、心配する必要はありません。

0

Cは、プログラムが正常に終了した場合(つまり、exitまたはmainからの返信)には、開いているファイルがすべて閉じられることを保証します。ただし、プログラムが異常終了した場合(例: NULLポインタを使用しているためオペレーティングシステムによって閉じられています。ファイルを閉じるのはオペレーティングシステムの責任です。したがって、予期せず終了した場合にファイルが不要になったら、ファイルが閉じられることを確認することをお勧めします。

その他の理由はリソースの制限です。ほとんどのオペレーティングシステムでは、ファイルの数に制限があります(他の多くのものと同様に)ので、不要になったらすぐにそれらのリソースを返すことをお勧めします。すべてのプログラムがすべてのファイルを無期限に開いたままにしておくと、システムは問題を非常に迅速に解決できます。

0

すべての正常なオペレーティングシステム(Linux、Windowsのいずれかの形式)は、プログラムが終了するとファイルを閉じます。非常にシンプルなプログラムをお持ちの場合、おそらく終了時にファイルを閉じる必要はありません。しかし、明示的にファイルを閉じると、次のような理由から、まだ良い習慣です:

  1. あなたはOSに任せる場合は、(整合性の問題につながる可能性がある、ファイルがクローズされる順序を制御することはできませんマルチファイルデータベースのような)。

  2. ファイルを閉じる際にエラーが発生した場合(I/Oエラー、領域不足エラーなど)、それらを報告する方法はありません。

  3. 対処が必要なファイルロックとの対話がある可能性があります。

  4. すべてのファイルがあることが、そのような方法であなたのシステムを設計し、他のクリーンアッププログラムが同時に必要であること(例えば、バッファのフラッシュ)

関連する問題