Domanda

Mi aspettavo che A :: ~ A () fosse chiamato in questo programma, ma non lo è:

#include <iostream>

struct A {
  ~A() { std::cout << "~A()" << std::endl; }
};

void f() {
  A a;
  throw "spam";
}

int main() { f(); }

Tuttavia, se cambio l'ultima riga in

int main() try { f(); } catch (...) { throw; }

quindi A :: ~ A () viene chiamato

Sto compilando con " Microsoft (R) 32-bit ++ Ottimizzazione del compilatore versione 14.00.50727.762 per 80x86 " da Visual Studio 2005. La riga di comando è cl / EHa my.cpp .

Il compilatore è corretto come al solito? Cosa dice lo standard in materia?

È stato utile?

Soluzione

Il distruttore non viene chiamato perché terminate () per l'eccezione non gestita viene chiamata prima che lo stack venga srotolato.

I dettagli specifici di ciò che dice la specifica C ++ sono al di fuori delle mie conoscenze, ma una traccia di debug con gdb e g ++ sembra confermarlo.

Secondo la bozza standard sezione 15.3 bullet 9:

9 If no matching handler is found in a program, the function terminate()
  (_except.terminate_)  is  called.  Whether or not the stack is unwound
  before calling terminate() is implementation-defined.

Altri suggerimenti

Stati di specifica del linguaggio C ++: Il processo di chiamare distruttori per oggetti automatici costruiti sul percorso da un blocco try a un'espressione di lancio è chiamato "impilamento dello stack". Il codice originale non contiene il blocco try, ecco perché non si verifica lo svolgersi dello stack.

Ho anche ipotizzato che il compilatore non generasse il codice relativo a " a " dato che non è referenziato ma comunque, non è il comportamento giusto in quanto il distruttore fa qualcosa che deve essere eseguito.

Quindi, ho provato in VS2008 / vc9 (+ SP1), Debug and Release e ~ A viene chiamato dopo che viene generata l'eccezione, uscendo da f () - questo è il comportamento giusto, se ho ragione.

Ora ho appena provato con VS2005 / vc8 (+ SP1) ed è lo stesso comportamento.

Ho usato i punti di interruzione per essere sicuro. Ho appena verificato con la console e ho il " ~ A " anche il messaggio. Forse hai sbagliato da qualche altra parte?

Mi dispiace non ho una copia dello standard su di me.
Vorrei sicuramente una risposta definitiva a questo, quindi qualcuno con una copia dello standard vuole condividere capitolo e versetto su ciò che sta accadendo:

Dal mio punto di vista terminare si chiama solo iff:

  • Il meccanismo di gestione delle eccezioni non riesce a trovare un gestore per un'eccezione generata.
    Di seguito sono riportati casi più specifici di questo:
    • Durante lo svolgimento dello stack, un'eccezione sfugge a un distruttore.
    • Un'espressione generata, un'eccezione sfugge al costruttore.
    • Un'eccezione sfugge al costruttore / distruttore di una statica non locale (cioè globale)
    • Un'eccezione sfugge a una funzione registrata con atexit ().
    • Un'eccezione sfugge a main ()
  • Tentativo di rilanciare un'eccezione quando al momento non si sta propagando alcuna eccezione.
  • Un'eccezione imprevista sfugge a una funzione con specificatori di eccezioni (tramite imprevisto)

Questa domanda è facile per google, quindi condivido la mia situazione qui.

Assicurati che la tua eccezione non superi il limite extern & C; o usi l'opzione MSVC / EH (Abilita le eccezioni C ++ = Sì con le funzioni C esterne (/ EH))

Nel secondo esempio, il dtor viene chiamato quando lascia il blocco try {}.

Nel primo esempio, il dtor viene chiamato quando il programma si arresta dopo aver lasciato la funzione main () --- entro la quale la cout potrebbe essere già stata distrutta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top