23 Stimmen

Ist das erneute Auslösen einer Ausnahme in einem verschachtelten "try" legal?

Ist das Folgende in C++ gut definiert, oder nicht? Ich bin gezwungen, Ausnahmen in Rückgabecodes zu "konvertieren" (die betreffende API wird von vielen C-Benutzern verwendet, daher muss ich sicherstellen, dass alle C++-Ausnahmen abgefangen und behandelt werden, bevor die Kontrolle an den Aufrufer zurückgegeben wird).

enum ErrorCode {…};
ErrorCode dispatcher() {
   try {
      throw;
   }
   catch (std::bad_alloc&) {
      return ErrorCode_OutOfMemory;
   }
   catch (std::logic_error&) {
      return ErrorCode_LogicError;
   }
   catch (myownstdexcderivedclass&) {
      return ErrorCode_42;
   }
   catch(...) {
      return ErrorCode_UnknownWeWillAllDie;
   }
}

ErrorCode apifunc() {
   try {
      // foo() might throw anything
      foo();
   }
   catch(...) {
      // dispatcher rethrows the exception and does fine-grained handling
      return dispatcher();
   }
   return ErrorCode_Fine;
}

ErrorCode apifunc2() {
   try {
      // bar() might throw anything
      bar();
   }
   catch(...) {
      return dispatcher();
   }
   return ErrorCode_Fine;
}

Ich hoffe, das Beispiel zeigt meine Absicht. Ich vermute, dass dies ein undefiniertes Verhalten ist, aber ich bin mir nicht sicher. Bitte geben Sie ggf. Zitate aus der Norm an. Alternative Ansätze sind ebenfalls willkommen.

Danke!

13voto

GManNickG Punkte 476445

Das ist in Ordnung. Die Ausnahme ist aktiv, bis sie abgefangen wird, und wird dann inaktiv. Aber es lebt, bis der Anwendungsbereich des Handlers endet. Aus dem Standard, Hervorhebung von mir:

§15.1/4: Der Speicher für die temporäre Kopie der ausgelösten Ausnahme wird auf eine nicht spezifizierte Weise zugewiesen, außer wie in 3.7.4.1 angegeben. Der temporäre Zustand bleibt so lange bestehen, wie ein Handler für diese Ausnahme ausgeführt wird.

Das heißt:

catch(...)
{ // <--

    /* ... */

} // <--

Zwischen diesen Pfeilen können Sie die Ausnahme wieder auslösen. Erst wenn der Anwendungsbereich des Handlers endet, hört die Ausnahme auf zu existieren.

Denken Sie daran, wenn Sie anrufen dispatch ohne eine aktive Ausnahme, terminate aufgerufen werden. Wenn dispatch in einem seiner Handler eine Ausnahme auslöst, dass wird sich die Ausnahme ausbreiten. Mehr Informationen unter eine verwandte Frage .

3voto

Kirill V. Lyadvinsky Punkte 92957

Desde dispatcher im Catch-Block aufgerufen throw wird eine Ausnahme auslösen. Wenn Sie die dispatcher außerhalb des Fangblocks dann terminate() aufgerufen wird (gemäß 15.1/8). Es gibt in jedem Fall kein undefiniertes Verhalten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X