Gestion des erreurs en C++ : try/catch et techniques avancées

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Gestion avancée des erreurs en C++ : de try/catch aux pratiques industrielles



La gestion des erreurs est l'une des pierres angulaires de la programmation industrielle. En C++, le développeur dispose non seulement du mécanisme classique try/catch, mais aussi de tout un arsenal de techniques avancées : du RAII aux garanties de sécurité des exceptions. Dans cet article, nous allons voir comment écrire du code C++ robuste qui gère correctement les défaillances, ne fuit pas les ressources et reste lisible.



1. Bases et pièges standards de try/catch



La syntaxe de base est connue de tous :



#include <iostream>#include <stdexcept>

void dangerousFunction(int value) { if (value < 0) { throw std::invalid_argument("Value must be non-negative"); } // ... travail avec 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;}


Points importants :

  • Attrapez par référence — catch (const std::exception& e) évite le découpage d'objets.
  • L'ordre des blocs catch est important : d'abord les exceptions les plus spécifiques, puis les générales.
  • N'abusez pas de catch (...) — il cache toutes les erreurs, y compris les critiques (par exemple, std::bad_alloc).
  • Ne lancez jamais d'exceptions depuis les destructeurs — cela entraîne un comportement indéfini (généralement une terminaison brutale).


2. RAII comme alternative à try/catch pour la gestion des ressources



RAII (Resource Acquisition Is Initialization) est le modèle clé du C++ qui rend les exceptions sûres. L'idée : la ressource est acquise dans le constructeur et libérée dans le destructeur. Si une exception se produit, les destructeurs de tous les objets créés sont appelés automatiquement (déroulement de la pile).



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

void processFile(const std::string& filename) { std::ifstream file(filename); // RAII : le fichier s'ouvre dans le constructeur 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); } // Le destructeur de file fermera le fichier automatiquement, // même en cas d'exception (par exemple, bad_alloc lors de push_back)}


Avantages du RAII par rapport au try/catch manuel :

  • Pas besoin d'écrire de blocs finally — les destructeurs garantissent le nettoyage.
  • Le code devient plus linéaire et lisible.
  • Les exceptions n'entraînent pas de fuites de mémoire, de descripteurs de fichiers, etc.


3. Garanties de sécurité des exceptions



En C++, on distingue trois niveaux de garanties pour les fonctions :



  • Garantie no-throw — la fonction ne lance jamais d'exception. Marquée noexcept.
  • Garantie forte — si une exception se produit, l'état du programme reste inchangé (opération atomique).
  • Garantie de base — en cas d'exception, il n'y a pas de fuite de ressources, les objets restent dans un état cohérent, mais leur valeur peut changer.


Exemple avec garantie forte (idiome copy-and-swap) :



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

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

Blogs

Book Recommendations