**RAII (Resource Acquisition Is Initialization)**は、C++におけるイディオムで、オブジェクトのライフタイムを通じてリソース(ファイル、メモリ、ソケットなど)のライフタイムを管理します。リソースはオブジェクトのコンストラクタで確保され、デストラクタで解放されます。
#include <fstream> void save_data(const std::string& filename, const std::string& data) { std::ofstream file(filename); // RAII: ファイルは自動的に閉じられます if (!file) throw std::runtime_error("ファイルを開けません"); file << data; } // ここでファイルは閉じられます
例外が発生した場合でも、デストラクタは呼び出され、リソースはリークしません。RAIIを使用しないと、メモリやファイルディスクリプタのリークに直面する可能性があります。
C++でtry/catchだけを使ってメモリリークを防ぐことは保証できますか?
いいえ、できません。try/catchを使うだけではリソースの解放を保証しません。保証するのはRAIIだけです。
int* arr = new int[10]; try { // arrの操作 throw std::runtime_error("うわっ"); } catch (...) { // delete[]がなければarrは解放されていません } // arrがリークします!
ストーリー
大規模なグラフィックプロジェクトで、ファイルディスクリプタの枯渇による定期的なクラッシュが発生しました。ファイルはRAII(std::fstream)でラップされずに関数内で開かれ、例外がスローされるとリソースは解放されませんでした。
ストーリー
ウェブサーバーのリクエストハンドラーでは、スマートポインタでラップされていない生のメモリが使用されていました。例外がスローされるとメモリが解放されず、パフォーマンスの低下やクラッシュを引き起こしていました。
ストーリー
画像処理プロジェクトでは、一時ファイルがオブジェクトでラップされずに作成されていました。例外がスローされるとファイルが削除されず、数ヶ月間の継続的な作業の後に/tmpがオーバーフローしました。