2010-09-24 14 views

risposta

19

in realtà hanno tre meccanismi:

  • eccezioni C++, implementati dal compilatore (try/catch)
  • Structured Exception Handling (SEH), fornito da Windows (__try/__except)
  • MFC macro di eccezione (TRY, CATCH - costruita su eccezioni SEH/C++ - vedere anche il commento di TheUndeadFish)

Le eccezioni C++ di solito garantiscono la pulizia automatica durante lo srotolamento dello stack (ad es. i distruttori di oggetti locali funzionano), gli altri meccanismi no.

Eccezioni C++ si verificano solo quando vengono generate esplicitamente. Eccezioni strutturate possono verificarsi per molte operazioni, ad es. a causa di un comportamento non definito, passando i puntatori non validi alle API, smontando il backing store di un file mappato in memoria e molti altri.

MFC ha introdotto le macro di eccezione per supportare le eccezioni anche se i compilatori non le implementavano.

+0

Solo per motivi di curiosità, MFC è stato concepito per funzionare su qualsiasi compilatore diverso da VC++? –

+2

Non sono richieste eccezioni C++ per garantire la pulizia. Compilare con/EHa. –

+0

MFC ha funzionato su Watcom C/C++ 10. In qualche modo. Senza i maghi e roba. – peterchen

6

Un'eccezione C++ è una funzionalità del linguaggio di programmazione C++. Un'eccezione strutturata è un concetto diverso del sistema operativo Windows. Questi due usano la sintassi simile, ma sono tecnicamente diversi. Le eccezioni strutturate di Windows non sono utilizzabili solo con C++ ma anche ad es. con C.

A volte una soluzione per unificare la gestione di entrambi: In un'applicazione Windows è possibile fornire una funzione di gestione, che cattura tutte le eccezioni strutturate e genera un'eccezione C++ (definita dall'utente).

4

Entrambi forniscono meccanismi per lo srotolamento dello stack quando si verificano errori.

Le eccezioni strutturate sono fornite da Windows, con supporto dal kernel. Vengono sollevate da Windows se si eseguono cose come accedere a una posizione di memoria non valida. Sono anche usati per supportare funzionalità come la crescita automatica dello stack. Sono usati abbastanza raramente da soli, ma le eccezioni linguistiche in C++, .NET e lingue simili sono spesso costruite su di esse. Utilizzi parole chiave speciali come __try e __catch per gestire queste eccezioni. Tuttavia, gestirli è relativamente difficile e soggetto a errori, in quanto è possibile interrompere funzionalità come l'espansione automatica dello stack e le eccezioni di linguaggio C++ potenzialmente in grado di rompere.

Le eccezioni C++ sono specificate dal linguaggio C++. I tipi di dati che vengono lanciati e catturati sono oggetti C++ (inclusa la possibilità di tipi primitivi). Il compilatore e il runtime implementano questi sopra il meccanismo di eccezione strutturata sottostante. Questo è ciò che ottieni se usi le parole chiave try, catch e throw della lingua C++.

Le eccezioni SEH hanno più funzionalità delle eccezioni C++, come la ripresa di supporto e i cosiddetti gestori "vettoriali" (che ricevono notifiche di eccezioni, ma non impediscono necessariamente lo srotolamento dello stack), ma a meno che non si sappia specificamente che si desidera usali, li eviterei. Probabilmente il loro uso più comune è scrivere un crash dump usando MiniDumpWriteDump se il tuo programma fa qualcosa di illegale o indefinito.

1

Eccezioni C++ funzioneranno su più piattaforme. Sfortunatamente SEH limiterà severamente la portabilità (tranne che potrebbe essere tra diverse versioni di Windows).

anche SEH sembra catturare un sacco di eccezioni native di Windows (come violazione di accesso, è stato specificato un handle non valido), ecc

7

Si tratta di un dettaglio di implementazione pesante, ma su Windows un C un'eccezione ++ è anche un'eccezione SEH. Il codice di eccezione è 0xE04D5343 (ultimi tre byte = 'MSC'). E tutto il supporto SEH regolare viene utilizzato per srotolare lo stack, eseguire il codice di pulizia automatica e filtrare l'eccezione in modo da selezionare la clausola catch corretta. Ottenere l'oggetto eccezione lanciato nell'espressione filtro è l'impianto idraulico che viene aggiunto dal CRT oltre a ciò che fornisce SEH. SEH supporta anche una clausola __finally ma che non viene utilizzata in C++ standard.

Un ulteriore dettaglio di implementazione è l'impostazione del compilatore/EH. L'impostazione predefinita (/ EHsc) consente al compilatore di ottimizzare il codice generato e sopprimere i filtri delle eccezioni necessari per eseguire la pulizia automatica. Se può vedere che nessuno del codice C++ emesso può generare un'eccezione. Questo è soprattutto un'ottimizzazione dello spazio, una piccola ottimizzazione del tempo per il codice x86 ma non per il codice x64. Per ottenere la pulizia automatica delle eccezioni SEH, è necessario compilare/EHa in modo che questa ottimizzazione venga eliminata.

Una buona strategia per sposare eccezioni C++ con SEH è utilizzare _set_se_translator() in modo da poter tradurre un'eccezione SEH in un'eccezione C++. Anche se spesso non è saggio prendere le eccezioni SEH, sono quasi sempre cattive.

+0

Will __try/__ tranne i blocchi catturano tutte le eccezioni SEH e tutte le eccezioni C++? – Alexandru

+0

È inoltre importante notare che _set_se_translator() viene chiamato una sola volta per ogni chiamata di funzione nello stack che ha blocchi try, in base a MSDN e deve essere impostato su una base per thread. – Alexandru