RAII (Resource Acquisition Is Initialization) è un'idioma di C++ che consente di gestire il ciclo di vita delle risorse (file, memoria, socket, ecc.) attraverso il ciclo di vita degli oggetti. Le risorse vengono allocate nel costruttore dell'oggetto e liberate nel distruttore.
#include <fstream> viod save_data(const std::string& filename, const std::string& data) { std::ofstream file(filename); // RAII: il file si chiuderà automaticamente if (!file) throw std::runtime_error("Impossibile aprire il file"); file << data; } // il file si chiuderà qui
In caso di eccezioni, il distruttore verrà comunque chiamato, quindi le risorse non andranno perse. Senza utilizzare RAII, si possono verificare perdite di memoria e dei descrittori di file.
È possibile garantire l'assenza di perdite di memoria in C++ usando solo try/catch?
No, non è possibile. L'uso di try/catch non garantisce l'allocazione delle risorse. Solo RAII offre questa garanzia.
int* arr = new int[10]; try { // Operazioni su arr throw std::runtime_error("Oops"); } catch (...) { // arr non liberato, a meno che non ci sia delete[] } // arr perso!
Storia
In un grande progetto di grafica, si verificavano periodicamente crash a causa dell'esaurimento dei descrittori di file. Si scoprì che i file venivano aperti in una funzione senza essere racchiusi in RAII (std::fstream), e durante il lancio di un'eccezione le risorse non venivano liberate.
Storia
In un handler di richieste di un server web si utilizzava memoria grezza senza una wrapper in smart-pointer - in caso di lancio di un'eccezione, la memoria non veniva liberata, portando a degrado delle performance e crash.
Storia
In un progetto di elaborazione delle immagini si creavano file temporanei senza un wrapper di oggetti. In caso di lancio di eccezioni, i file non venivano rimossi, portando a un riempimento di /tmp sul server dopo alcuni mesi di lavoro continuo.