C ++ ed eccezioni di sistema

1

Perché il C ++ standard non rispetta le eccezioni del sistema (straniero o hardware)?

es. quando si verifica un dereferenziamento del puntatore nullo, lo stack non viene svolto, i distruttori non vengono chiamati e RAII non funziona.

Il consiglio comune è "usare l'API di sistema". Ma su alcuni sistemi, in particolare su Win32, questo non funziona. Per abilitare lo sbobinamento dello stack per questo codice C ++

// class Foo;
// void bar(const Foo&);
bar(Foo(1, 2));

si dovrebbe generare qualcosa come questo codice C

Foo tempFoo;
Foo_ctor(&tempFoo);
__try {
    bar(&tempFoo);
}
__finally {
    Foo_dtor(&tempFoo);
}
Foo_dtor(&tempFoo);

ed è impossibile implementarlo come libreria C ++.

UPD: Lo standard non vieta la gestione delle eccezioni di sistema. Ma sembra che compilatori popolari come g ++ non rispettino le eccezioni di sistema su qualsiasi piattaforme solo perché lo standard non richiede questo.

L'unica cosa che voglio - è usare RAII per rendere il codice leggibile e il programma affidabile. Non voglio mettere try \ end hand-crafting attorno ad ogni chiamata a codice sconosciuto. Ad esempio in questo codice riutilizzabile, AbstractA::foo è un codice sconosciuto:

void func(AbstractA* a, AbstractB* b) {
    TempFile file;
    a->foo(b, file);
}

Forse uno passerà a func un'implementazione di AbstractA , che ogni venerdì non controllerà se b è NULL, quindi la violazione di accesso avverrà, l'applicazione terminerà e il file temporaneo non verrà eliminato. Quanti mesi di utilizzo soffriranno a causa di questo problema, fino a quando uno degli autori di func o autore di AbstractA farà qualcosa con esso?

Correlati: È "catch (...) {throw; } "una cattiva pratica?

    
posta Abyx 07.12.2011 - 15:47
fonte

3 risposte

4

Lo standard C ++ non rispetta le eccezioni di sistema perché è stato progettato per essere utilizzabile su una vasta gamma di piattaforme (molto più ampia delle piattaforme basate su PC). Sarebbe impossibile fornire una sorta di supporto per ciascuna piattaforma nello standard. Questo è lasciato per le implementazioni e giustamente.

La mia reazione alla parte irragionevole della tua domanda: eccezioni Win32 sono lanciate in casi fatali da cui non puoi veramente recuperare. __try & anche gli amici lavorano in C ++ (non solo per C), e puoi chiamare manualmente il distruttore se necessario (ma il tuo programma è in uno stato in cui non verrà più eseguito, quindi a meno che quel distruttore non rilasci qualcosa che il sistema operativo non avrebbe 't normalmente rilasciato dopo che il processo è terminato, non c'è molto punto).

Modifica: in risposta al tuo aggiornamento: stai ancora scorrazzando. Non è come l'hai immaginato, e allora? Puoi ancora proteggerti dallo scenario che hai citato come esempio. Si utilizza il codice specifico della piattaforma per rilevare l'eccezione di sistema, chiudere il file e bloccarsi in modo corretto. Potrebbe esserci un modo migliore per farlo; fai una domanda specifica su SO. Isolare il codice di terze parti non è banale e probabilmente richiede un certo sforzo per raggiungere (un buon esempio di questo è il plugin flash notoriamente instabile che ora viene eseguito isolato nella maggior parte dei principali browser).

g++ doesn't respect system exceptions on any platforms just because standard doesn't require this

Anche se implementa un buon numero di estensioni, gcc sceglie le architetture, non le piattaforme. Gcc stesso è portato su piattaforme diverse ma questa è una storia diversa; la parte di generazione del codice dipende dall'architettura, non dalla piattaforma. Questo spiega perché non sarebbe possibile supportare le eccezioni del sistema Windows senza grandi sforzi.

    
risposta data 07.12.2011 - 16:03
fonte
3

puoi configurare MSVC per rilevare le eccezioni di sistema in un blocco catch(...) . Questo è esattamente come lo scopo previsto dagli standard - le implementazioni forniscono meccanismi per catturare gli errori lanciati dalle loro implementazioni. A rigor di termini, sono solo UB e non devono fornire un meccanismo qualsiasi .

Tuttavia, c'è una tendenza crescente, sia all'interno che all'esterno di Microsoft, a non codificare in modo difensivo, ad esempio IsBadXXXPtR ora è strongmente sconsigliato.

    
risposta data 07.12.2011 - 16:29
fonte
1

Come programmatore C ++ sono contento che le eccezioni hardware siano completamente diverse.

Immagina se non lo fossero. All'improvviso, il codice che non contiene dichiarazioni throw contiene ora un'eccezione. Potrebbe anche provenire da una funzione dichiarata come throw() o nothrow .

Oltre a ciò, per gestire correttamente queste eccezioni, il programmatore deve conoscere abbastanza bene l'hardware e la piattaforma. In tal caso, può anche utilizzare le funzioni fornite dalla piattaforma per gestirlo. La semplice scrittura di un blocco catch non si avvicina affatto alla corretta definizione di un riferimento a un puntatore o una divisione per zero.

    
risposta data 08.06.2012 - 01:19
fonte

Leggi altre domande sui tag