C ++, __try e try / catch / finally

Mi sto chiedendo un po ‘su C ++ try / catch / finally blocks. Ho visto questi comandi con due underscore come __try. Ma i progetti MVSC 2010 funzionano anche senza i caratteri di sottolineatura. Quindi, quando hai bisogno di questi underscore?

Su Windows, le eccezioni sono supportate a livello di sistema operativo. Chiamato Structured Exception Handling (SEH), sono l’equivalente approssimativo dei segnali Unix. I compilatori che generano codice per Windows in genere ne approfittano, usano l’infrastruttura SEH per implementare eccezioni C ++.

In linea con lo standard C ++, le parole chiave throw and catch sono sempre e solo le eccezioni C ++. Il codice di eccezione SEH corrispondente per il compilatore MSVC è 0xe06d7343. Gli ultimi 3 byte sono il codice ASCII per “msc”.

Unificarlo con il supporto del sistema operativo significa anche che i distruttori C ++ verranno chiamati durante lo sbobinamento dello stack per un’eccezione SEH. Il codice che esegue lo svolgimento è all’interno di Windows e tratta il SEH generato da un lancio esattamente allo stesso modo di qualsiasi SEH. Tuttavia, il compilatore Microsoft ha un’ottimizzazione che tenta di evitare di generare il codice richiesto che garantisce che i distruttori vengano chiamati in tutti i casi. Se può provare che non esiste alcuna istruzione di lancio all’interno del blocco di ambito che controlla la durata dell’object, salta il codice di registrazione. Questo non è compatibile con le eccezioni SEH asincrone, è necessario utilizzare l’opzione di compilazione / EHa per sopprimere questa ottimizzazione se si intende ottenere eccezioni SEH.

Esistono molti tipi di eccezioni SEH. Quelli che possono essere generati dal sistema operativo sono elencati nel file di intestazione SDK ntstatus.h. Inoltre, è ansible utilizzare il codice che utilizza SEH per implementare la propria gestione delle eccezioni, che utilizzerà il proprio codice di eccezione. Come .NET, le eccezioni gestite utilizzano il codice di eccezione 0xe0434f4d (“com”).

Per ottenere le eccezioni SEH in un programma C ++, è necessario utilizzare la parola chiave __try non standard. La parola chiave __except è analoga alla parola chiave catch di C ++. Ha più funzionalità, si specifica un’espressione filtro di eccezione che determina se deve essere rilevata o meno un’eccezione triggers. Tutto è ansible, ma in genere si guardano solo le informazioni sulle eccezioni passate per vedere se si è interessati a gestirle. La parola chiave __finally consente di scrivere codice eseguito dopo che l’eccezione è stata gestita. Nessun equivalente per quello in C ++, ma non è raro in altre lingue.

Tutto questo è abbastanza scarsamente documentato come sottolineato nei commenti. La prova è nel budino. Ecco un esempio di programma con cui puoi giocare. Dimostra come le eccezioni SEH consentano ancora di chiamare i distruttori C ++, purché si compili con / EHa e in che modo le eccezioni C ++ siano implementate su SEH. Richiesto compilatore MSVC, eseguito con Ctrl + F5 per evitare che il debugger sia utile:

 #include "stdafx.h" #include  #include  // NOTE: the value of the C/C++, Code Generation, Enable C++ Exceptions setting in important // Try it both with /EHsc (the default) and /EHa to see the difference class Example { public: ~Example() { std::cout << "destructed" << std::endl; } }; int filterException(int code, PEXCEPTION_POINTERS ex) { std::cout << "Filtering " << std::hex << code << std::endl; return EXCEPTION_EXECUTE_HANDLER; } void testProcessorFault() { Example e; int* p = 0; *p = 42; } void testCppException() { Example e; throw 42; } int main() { __try { testProcessorFault(); } __except(filterException(GetExceptionCode(), GetExceptionInformation())) { std::cout << "caught" << std::endl; } __try { testCppException(); } __except(filterException(GetExceptionCode(), GetExceptionInformation())) { std::cout << "caught" << std::endl; } return 0; } 

Produzione:

 Filtering c0000005 destructed caught Filtering e06d7363 destructed caught 

__try / __except serve per intercettare SEH (errori generati da Windows) non per rilevare eccezioni generali.

try / catch è ciò che lo standard C ++ specifica per gestire le eccezioni C ++ generali.

Per il codice C ++ standard che scrivi devi sempre usare try / catch e non __try / __except

Inoltre, finally , non è il costrutto specificato in C ++ Standard, funziona per te perché è un’estensione del compilatore Microsoft .

__try/__except Microsoft specifico Se vuoi che il tuo codice sia compilabile con altri compilatori (per examplec g ++) (o) in un altro OS evita di usarli, e segui le dichiarazioni standard try/catch