RAII (Resource Acquisition Is Initialization) is een C++-idioma dat het levensduurbeheer van resources (bestanden, geheugen, sockets, enz.) door de levensduur van objecten mogelijk maakt. Resources worden toegewezen in de constructor van een object en vrijgegeven in de destructor.
#include <fstream> void save_data(const std::string& filename, const std::string& data) { std::ofstream file(filename); // RAII: bestand sluit automatisch if (!file) throw std::runtime_error("Kan bestand niet openen"); file << data; } // bestand sluit hier
Wanneer er uitzonderingen optreden, zal de destructor nog steeds worden aangeroepen, waardoor resources niet in een lek terechtkomen. Als RAII niet wordt gebruikt, kunnen er geheugen- en bestandshandleidingenlekken optreden.
Kan men het ontbreken van geheugenlekken in C++ garanderen door alleen try/catch te gebruiken?
Nee, dat kan niet. Het gebruik van try/catch garandeert niet dat resources worden vrijgegeven. Alleen RAII biedt een garantie.
int* arr = new int[10]; try { // Werken met arr throw std::runtime_error("Oops"); } catch (...) { // arr is niet vrijgegeven, tenzij delete[] is aangeroepen } // arr lekt!
Verhaal
In een groot grafisch project gebeurden er regelmatig crashes door uitputting van bestandshandleidingen. Het bleek dat bestanden in een functie werden geopend zonder gebruik te maken van RAII (std::fstream), en bij het gooien van een uitzondering werden de resources niet vrijgegeven.
Verhaal
In de verzoekverwerker van de webserver werd ruwe geheugen gebruikt zonder te wikkelen in een smart-pointer – bij het gooien van een uitzondering werd het geheugen niet vrijgegeven, wat leidde tot prestatieverlies en crashes.
Verhaal
In een afbeeldingsverwerkingsproject werden tijdelijke bestanden gemaakt zonder ze in objecten te wikkelen. Bij het gooien van uitzonderingen werden bestanden niet verwijderd, wat leidde tot een overflow van /tmp op de server na enkele maanden ononderbroken gebruik.