RAII (Resource Acquisition Is Initialization) es un idiomático de C++ que permite gestionar el tiempo de vida de los recursos (archivos, memoria, sockets, etc.) a través del tiempo de vida de los objetos. Los recursos se adquieren en el constructor del objeto y se liberan en el destructor.
#include <fstream> void save_data(const std::string& filename, const std::string& data) { std::ofstream file(filename); // RAII: el archivo se cerrará automáticamente if (!file) throw std::runtime_error("No se puede abrir el archivo"); file << data; } // el archivo se cerrará aquí
Cuando ocurren excepciones, el destructor todavía se invocará, y los recursos no se filtrarán. Si no se utiliza RAII, se pueden enfrentar fugas de memoria y descriptores de archivos.
¿Se puede garantizar la ausencia de fugas de memoria en C++ utilizando solo try/catch?
No, no se puede. Simplemente usar try/catch no garantiza la liberación de los recursos. Solo RAII proporciona esa garantía.
int* arr = new int[10]; try { // Trabajo con arr throw std::runtime_error("Ups"); } catch (...) { // arr no se liberó, a menos que se utilice delete[] } // arr se filtró!
Historia
En un gran proyecto de gráficos, ocurrieron caídas periódicas debido al agotamiento de descriptores de archivos. Resultó que los archivos se abrían en una función sin estar envueltos en RAII (std::fstream), y al lanzar una excepción, los recursos no se liberaban.
Historia
En el manejador de solicitudes de un servidor web se utilizaba memoria cruda sin envolverla en un puntero inteligente; en caso de lanzar una excepción, la memoria no se liberaba, lo que llevaba a la degradación del rendimiento y a caídas.
Historia
En un proyecto de procesamiento de imágenes, se creaban archivos temporales sin envoltura en objetos. Al lanzar excepciones, los archivos no se eliminaban, lo que llevaba al desbordamiento de /tmp en el servidor después de varios meses de funcionamiento continuo.