Manejo de errores en C++: try/catch y técnicas avanzadas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Manejo avanzado de errores en C++: de try/catch a prácticas industriales



El manejo de errores es una de las piedras angulares de la programación industrial. En C++, el desarrollador no solo tiene acceso al mecanismo clásico try/catch, sino también a todo un arsenal de técnicas avanzadas: desde RAII hasta garantías de seguridad de excepciones. En este artículo, analizaremos cómo escribir código C++ robusto que maneje fallos correctamente, no pierda recursos y se mantenga legible.



1. Fundamentos y trampas estándar de try/catch



La sintaxis básica es conocida por todos:



#include <iostream>#include <stdexcept>

void dangerousFunction(int value) { if (value < 0) { throw std::invalid_argument("Value must be non-negative"); } // ... trabajo con value}

int main() { try { dangerousFunction(-5); } catch (const std::invalid_argument& e) { std::cerr << "Error: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "Generic error: " << e.what() << std::endl; } catch (...) { std::cerr << "Unknown exception caught" << std::endl; } return 0;}


Puntos importantes:

  • Capture por referencia — catch (const std::exception& e) evita el corte de objetos.
  • El orden de los bloques catch es importante: primero las excepciones más específicas, luego las generales.
  • No abuse de catch (...) — oculta todos los errores, incluidos los críticos (por ejemplo, std::bad_alloc).
  • Nunca lance excepciones desde destructores — esto provoca un comportamiento indefinido (generalmente una terminación abrupta).


2. RAII como alternativa a try/catch para la gestión de recursos



RAII (Resource Acquisition Is Initialization) es el patrón clave de C++ que hace que las excepciones sean seguras. La idea: el recurso se adquiere en el constructor y se libera en el destructor. Si ocurre una excepción, los destructores de todos los objetos creados se llaman automáticamente (desenrollado de pila).



#include <fstream>#include <vector>#include <stdexcept>

void processFile(const std::string& filename) { std::ifstream file(filename); // RAII: el archivo se abre en el constructor if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filename); }

std::vector<int> data; int value; while (file >> value) { data.push_back(value); } // El destructor de file cerrará el archivo automáticamente, // incluso si ocurre una excepción (por ejemplo, bad_alloc en push_back)}


Ventajas de RAII sobre try/catch manual:

  • No es necesario escribir bloques finally — los destructores garantizan la limpieza.
  • El código se vuelve más lineal y legible.
  • Las excepciones no provocan fugas de memoria, descriptores de archivos, etc.


3. Garantías de seguridad de excepciones



En C++, se distinguen tres niveles de garantía para las funciones:



  • Garantía No-throw — la función nunca lanza excepciones. Se marca con noexcept.
  • Garantía Fuerte — si ocurre una excepción, el estado del programa permanece sin cambios (operación atómica).
  • Garantía Básica — ante una excepción, no hay fugas de recursos, los objetos permanecen en un estado consistente, pero su valor puede cambiar.


Ejemplo con garantía fuerte (idioma copy-and-swap):



#include <algorithm>  // para std::swap#include <vector>#include <stdexcept>

class SafeVector { std::vector<int> data_;public: void push_back(int value) { // 1. Se crea

Blogs

Book Recommendations