1. ホーム
  2. ruby

[解決済み] RubyのFile.openとf.closeの必要性

2023-01-17 01:49:52

質問

多くのプログラミング言語では、ファイルを扱う際の流れはopen-use-closeであることが常識となっています。しかし、rubyのコードでFile.openの呼び出しが一致しないものを何度も見ましたし、さらには という珠玉の知識を発見しました。 を見つけました。

I/Oストリームは、ガベージコレクタによって要求されると自動的に閉じられます。

darkredandyellow この問題に対するフレンドリーなircのテイク。

[17:12] そうそう、あと、ファイルディスクリプタの数は通常OSによって制限されています。

[17:29] 利用可能なファイルディスクリプタを簡単に使い果たすことができると仮定します。
の前に ガベージコレクタがクリーンアップする前に、利用可能なファイル記述子を簡単に使い果たすことができると思います。

  1. 明示的にファイルを閉じる必要があるのか
  2. もしそうなら、なぜGCは自動終了するのですか?
  3. そうでないなら、なぜそのようなオプションがあるのでしょうか?

どのように解決するのですか?

<ブロッククオート

Rubyのコードで、マッチしないものを何度も見ました。 File.open を呼び出す

例を挙げていただけますか?私は、以下のような初心者が書いたコードでしか見たことがありません。 を欠いている ファイルを操作するためのフローは open-use-close" であるという、ほとんどのプログラミング言語における共通の知識を持っていない初心者が書いたコードで見られるだけです。

経験豊富な Rubyist は、ファイルを明示的に閉じるか、より慣用的な方法として、ブロック形式の File.open というブロック形式で、自動的にファイルを閉じます。その実装は基本的に次のようなものです。

def File.open(*args, &block)
  return open_with_block(*args, &block) if block_given?
  open_without_block(*args)
end

def File.open_without_block(*args)
  # do whatever ...
end

def File.open_with_block(*args)
  yield f = open_without_block(*args)
ensure
  f.close
end

スクリプトは特別なケースです。スクリプトは一般に非常に短く実行され、ファイル記述子をほとんど使用しないので、スクリプトが終了したときにオペレーティング システムがいずれにせよそれらを閉じるので、単純に閉じることは意味がありません。

明示的に閉じる必要があるのでしょうか?

はい。

<ブロッククオート

もしそうなら、なぜGCは自動終了するのでしょうか?

なぜなら、GCがオブジェクトを収集した後、もうファイルをクローズする方法がないからで、したがって、ファイル記述子をリークすることになります。

ファイルをクローズするのはガベージコレクタではないことに注意してください。ガベージコレクターは、オブジェクトを収集する前に、オブジェクトのファイナライザーをすべて実行するだけです。それは、たまたま File クラスはファイルを閉じるファイナライザを定義しています。

そうでない場合、なぜオプションがあるのでしょうか?

無駄なメモリは安価ですが、無駄なファイル記述子はそうではないからです。したがって、ファイル記述子の寿命をメモリのいくつかのチャンクの寿命に結びつけることは意味を持ちません。

あなたは単に いつ ガベージコレクタが実行されるかを予測することはできません。予測することさえできません。 もし が実行されるかどうかを予測することもできません。 もしメモリ不足にならなければ、ガベージコレクタは決して実行されず、したがってファイナライザは決して実行されず、したがってファイルは決してクローズされません。