More Effective C++ 項目9 リソースリークを防ぐためにデストラクタを使う
新訂版 More Effective C++ (AddisonーWesley professional co)
- 作者: スコット・メイヤーズ,安村通晃,伊賀聡一郎,飯田朱美,永田周一
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2007/06/29
- メディア: 単行本(ソフトカバー)
- 購入: 8人 クリック: 129回
- この商品を含むブログ (43件) を見る
項目9 リソースリークを防ぐためにデストラクタを使う
メモリを確保した後、解放するまでの間の例外は、リソースリークの危険がある。
void function(istream& dataSource) { while (dataSource) { // データがある間、 Sample* ps = readSample(dataSource); // readして、 ps->process(); // 処理して、 delete ps; // 削除する。 } }
この場合、process()で例外が発生すると、deleteが実行されず、リソースリークしてしまう。
try/catchで書きなおすと以下のようになる。
void function(istream& dataSource) { while (dataSource) { Sample* ps = readSample(dataSource); try { ps->process(); } catch (...) { // 例外を受け取る delete ps; // 例外発生時、リソースリークを防ぐ throw; // 例外を伝搬させる } delete ps; // 例外が発生していないとき、リソース解放 } }
この方法だと、正常なパスと例外発生時のパスの両方にクリーンアップコードを書かなければならない。
自動的に破棄させるためにはスマートポインタを使う。
C++にはauto_ptrというクラステンプレートが含まれていて、それを使えば以下のようになる。
void function(istream& dataSource) { while (dataSource) { auto_ptr<Sample> ps(readSample(dataSource)); // readして、auto_ptrに入れる ps->process(); } }
これでスコープから外れてauto_ptrのデストラクタが呼ばれたとき、リソースが解放される。
まとめ
リソースをオブジェクトの中にカプセル化し、デストラクタで解放すればリソースリークを通常は回避できる。
コンストラクタでの例外や、リソースの自動破棄の最中の例外はこの後の項目で出てくる。