2010-12-10 19 views
14

Se sto creando un nuovo progetto in C++ non gestito, Visual Studio 2008 o versione successiva, quale modello di gestione delle eccezioni voglio seguire?Codice non gestito di Visual C++: utilizzare/EHa o/EHsc per le eccezioni C++?

Capisco che l'opzione/EHa si traduce in un codice meno efficiente e rileva anche le eccezioni SEH, giusto?

Quindi mi sono liberato di questa opzione e di solito uso/EHsc, in modo che io stia rilevando solo eccezioni C++ che vengono effettivamente generate e non rilevando violazioni di accesso e altre esecuzioni strutturate, in catch (...) gestori. Se c'è una violazione di accesso nel mio codice, non voglio che venga mascherata da un fermo (...) {}.

Codice con altri che vogliono prendere (...) {} per non fare nulla e vogliono persino che lo faccia se c'è una violazione di accesso, che mi sembra una pessima idea. Se c'è un bug a causa di una cattiva programmazione, non si vuole infilarci le dita nelle orecchie e dire ad alta voce "La la la la!" in modo che tu non debba avere il crash del programma? Infatti, se il codice è ora in uno stato negativo a causa di un errore di codifica, vuoi veramente che il codice continui?

Quindi il mio pensiero generale è che/EHa crea un codice più grande/più lento e consente ai programmatori di cavarsela con il codice di scrittura che, se è presente un errore irreversibile, continuerà a funzionare in uno stato indefinito.

BTW, sto parlando di applicazioni e codice di servizio che è quello che stiamo scrivendo per la maggior parte. Driver di dispositivo non di livello basso o simili.

Si prega di valutare con i vostri pensieri.

risposta

16

/EHa fa due cose. Innanzitutto, sopprime un'ottimizzazione che omette i filtri delle eccezioni che chiamano automaticamente i distruttori delle variabili di classe locali se l'analizzatore di codice non può vedere alcun codice che possa lanciare un'eccezione C++. Ciò rende lo stack unwinding sicuro per qualsiasi tipo di eccezione, non solo un'eccezione C++. L'overhead per questi filtri delle eccezioni è il tempo su x86 e lo spazio su entrambi x86 e x64.

E sì, altera il comportamento di catch (...), ora filtra anche qualsiasi eccezione SEH, non solo C++. Questo è davvero un azzardo perché si prendono tutte le cose veramente cattive, le eccezioni hardware asincrone. Anche se personalmente non penso che catturare tutte le eccezioni del C++ sia molto difendibile, hai ancora una vaga idea di quanto sia stato mutato lo stato del programma e perché non ha funzionato.

Realisticamente, è necessario passare all'utilizzo di __try/__except in modo da poter scrivere il proprio filtro delle eccezioni ed evitare di catturare quelli negativi. Il codice di eccezione per le eccezioni C++ è 0xe04d5343 ("MSC"). Utilizzare _set_se_translator() sarebbe un altro approccio.

4

Io uso/EHa perché è sicuro con .NET interop, mentre/EHsc potrebbe non esserlo; vedi Destructors not called when native (C++) exception propagates to CLR component per esempio.

Tuttavia, se per uno specifico bit di codice le prestazioni extra sono davvero importanti e non è necessaria la compatibilità con .NET (o qualsiasi altra cosa), quindi sicuro,/EHsc suona bene.

Né/EHsc né/EHa catturano la maggior parte degli errori di memoria, quindi l'utilizzo di questi per rilevare le violazioni di accesso è un caso senza speranza.

+2

Non si dovrebbe mai provare a rilevare le violazioni di accesso in ogni caso. –

+1

Questa è la mia comprensione ... ma ho persone che scrivono catch (...) {} e se/EHa è selezionato, allora sarebbe seppellire la violazione di accesso credo. È una cosa da prendere (...) {cleanup_stuff; gettare; } ma anche in quel caso, se si tratta di una violazione di accesso che viene catturata, sei sicuro che cleanup_stuff farà il suo lavoro? Sei in cattivo stato, quindi probabilmente penserei che il programma sia il migliore in assoluto. – MarkS

+3

Sto lavorando su un sistema client/server in cui se il server ha un'eccezione (idealmente, qualsiasi eccezione, inclusa la violazione di accesso), vorrei inviare il messaggio di eccezione al client prima di consentire l'arresto anomalo del thread del server. Altrimenti, il server smette semplicemente di rispondere. –