2011-01-14

fcloseはリソース解放を失敗しない

厳密に言うと、fcloseはエラーを返す可能性がある。しかし、それは、通常のプログラマーが考えるような失敗ではない。 。fcloseが失敗した後、プログラマがストリームに対してできることは何もない。

何故か。規格で明確に、fclose呼び出しが成功しようと失敗しようと、渡されたストリームは閉じられ、ストリームに関連付けられているバッファーも解放されることが保証されている。つまり、たとえfclose呼び出しが失敗したとしても、fcloseに渡したストリームは、すでに閉じられているのである。そのストリームに対して行えることは何も無い。

あるいは、無効なストリームを渡したという場合が考えられる。これは、無効なストリームをfcloseに渡したプログラマーの責任である。誰が失敗したかといえば、プログラマーである。fcloseの責任ではない。

まとめ:正しく実装されたfcloseは、リソース解放を絶対に失敗しない。たとえエラーを返したとしても、妥当なストリームを渡していた場合は、必ず解放される。

一般に、リソース解放というカテゴリーに分類されるライブラリは失敗すべきではない。たとえば、Win32 APIのCloseHandleも、同じ意味で、失敗はしない。CloseHandleに渡した妥当なハンドルは必ず解放される。

1 comment:

Anonymous said...

fclose(3)ではなくclose(2)の話ですが、ストレージ側の都合でclose(2)が失敗し、ファイルが中途半端な状態で書き込まれてしまい、かなりの被害を出してしまった同僚がいました。

ハンドルが開放されることと、期待した結果が得られることは分けて考えなければいけないと思います。おそらくここでは、ハンドルが開放されない事を「失敗」と表現されているのではないかとは思いますが。

アプリケーション側では、期待した結果が得られなかったときには、closeに失敗したファイルを消して次の処理に進まないようにしたり、ログや監視によって検知できるようにする必要があるので、そのストリームに対してできることが無くても、アプリケーションとしてやることが無いわけではありません。

デストラクタの話を想定して書かれていると思いますので、横槍ですみませんが、身の回りで終了処理の失敗に関連する事故が続いたので、気になって書き込みました。個人的には、終了処理(termination)と、破棄(destruction)・開放(release)処理は分けるべきだろうと思っています。