Spécifications d'exception

Les spécifications d'exceptions sont une fonctionnalité du langage C++ qui est déconseillée dans C++11. Elles étaient conçues pour fournir des informations résumées concernant les exceptions pouvant être levées à partir d'une fonction, mais dans la pratique elles se sont avérées problématiques. La seule spécification d'exception qui s'est révélée quelque peu utile est la spécification throw(). Par exemple :

void MyFunction(int i) throw();

indique au compilateur que la fonction ne lève pas d'exception. Cela revient à utiliser __declspec (nothrow). Son utilisation est considérée comme facultative. La norme ISO C++11 voit l'introduction de l'opérateur noexcept, mais la prise en charge de cette fonctionnalité n'est pas encore présente dans Visual C++.

Visual C++ s'éloigne de la norme ISO C++ dans son implémentation des spécifications d'exceptions. Le tableau suivant résume l'implémentation Visual C++ des spécifications d'exceptions :

Spécification d'exception

Signification

throw()

La fonction ne lève pas d'exception. Toutefois, si une exception est levée à partir d'une fonction marquée throw(), le compilateur Visual C++ n'effectue pas d'appel inattendu (consultez inattendu (CRT) et inattendue (<exception>) pour plus d'informations). Si une fonction est marquée avec throw(), le compilateur Visual C++ suppose qu'elle ne lève pas d'exception C++ et il génère le code en conséquence. En raison des optimisations de code qui peuvent être exécutées par le compilateur C++ (suite à l'hypothèse selon laquelle la fonction ne lève pas d'exception C++), si une fonction lève une exception, le programme peut ne pas s'exécuter correctement.

throw(...)

La fonction peut lever une exception.

throw(type)

La fonction peut lever une exception de type type. Toutefois, dans Visual C++ .NET, ceci est interprété comme throw(...). Consultez Spécificateurs d'exceptions de fonctions.

Si la gestion des exceptions est utilisée dans une application, il doit exister une ou plusieurs fonctions qui gèrent les exceptions levées. Toute fonction appelée entre celle qui lève une exception et celle qui gère l'exception doit être capable de lever l'exception.

Le comportement de levée d'exception d'une fonction dépend des facteurs suivants :

  • si vous compilez la fonction sous C ou C++ ;

  • l'option du compilateur /EH que vous utilisez ;

  • si vous spécifiez de manière explicite la spécification d'exception.

Les spécifications d'exceptions explicites ne sont pas autorisées sur les fonctions C.

Le tableau suivant résume les comportements de levée d'exception d'une fonction :

Fonction

/EHsc

/EHs

/EHa

/EHac

Fonction C

throw()

throw(...)

throw(...)

throw(...)

Fonction C++ sans spécification d'exception

throw(...)

throw(...)

throw(...)

throw(...)

Fonction C++ avec spécification d'exception throw()

throw()

throw()

throw(...)

throw(...)

Fonction C++ avec spécification d'exception throw(...)

throw(...)

throw(...)

throw(...)

throw(...)

Fonction C++ avec spécification d'exception throw(type)

throw(...)

throw(...)

throw(...)

throw(...)

Exemple

// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>

void handler() {
   printf_s("in handler\n");
}

void f1(void) throw(int) {
   printf_s("About to throw 1\n");
   if (1)
      throw 1;
}

void f5(void) throw() {
   try {
      f1();
   }
   catch(...) {
      handler();
    }
}

// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
//   f1();
// }

void __declspec(nothrow) f2(void) {
   try {
      f1();
   }
   catch(int) {
      handler();
    }
}

// only valid if compiled without /EHc 
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
   f1();
}

int main() {
   f2();

   try {
      f4();
   }
   catch(...) {
      printf_s("Caught exception from f4\n");
   }
   f5();
}
  

Voir aussi

Référence

Instructions try, throw et catch (C++)

Gestion d'exceptions C++