- ベストアンサー
結局 deleteしないとダメ? ファイナライザー万能主義は理解不足?
安直に後始末はファイナライザ部に書いておけば、OKと思っていましたが、実行させると実行時エラー?になり正しくファイルに書き込めていません。リソースを解放するタイミングが理解できていないです。 書き込んでcloseすると確実ですが、何度もopenしないといけないので、オブジェクトの有効期間開きっぱなしで処理させて、オブジェクト消滅と共にクローズさせたいです。 以下、無理やり動作させたソースです。 この考え方は正しいでしょうか? /* ファイナライザに後始末処理を入れておけば すべてうまくいくと理解していたのですが そんな単純なものではないのでしょうか? */ #using <system.dll> using namespace System; using namespace System::IO; ref class Test_A { StreamWriter^ sw; // ファイルのオープン void open(void){ try { sw = gcnew StreamWriter( "test.log", true); } catch ( Exception^ ex) { Console::WriteLine("オープンエラー"); } } // ファイルのクローズ void close(){ if (sw){ sw->Close(); } } public: // コンストラク Test_A(){ sw = nullptr; open(); } // デストラクタ ~Test_A(){ this->!Test_A(); // ← これを書き、delete a;とすると、正しく書き込まれて変な例外ダイアログメッセージが表示されなくなる。 } // ファイナライザー !Test_A(){ close(); // ファイナライザで後処理すれば、万事OKではない?? } // ファイルの書き込み void Write(String^ log){ try { sw->Write(log); } catch ( Exception^ ex ) { Console::WriteLine("書き込みでエラー"); } } }; //------------------------------------- // メイン //------------------------------------- int main(void){ Test_A^ a = gcnew Test_A(); a->Write("delete aと、~Test_Aに処理を施さないと、正しく書き込めない。\n"); delete a; // ←これが無いと、変なダイアログメッセージが表示される、しかも正しく書き込めない。 return 0; }
- みんなの回答 (3)
- 専門家の回答
補足
非常にわかりやすい説明で、ありがとうございます。 上書きの件は理解できましたが、 まだ理解できないのは、ハンドル自体がポインタのように解放するということでnewでなく、gcnew (C++/CLI) は、GC(ガーベージコレクト)なので、勝手に解放してくると思いました。 例外的に直ぐに解放する必要があるファイルやソケットなどリソースは明示的にdeleteで解放する必要があるということでしょうか?