2011-01-25 17 views
7

esiste un modo multipiattaforma per gestire le eccezioni della CPU come errori di segmentazione o divisione per zero? Diciamo, ho bisogno di chiamare alcune funzioni potenzialmente non sicure (ad esempio da un file plug-in), che possono causare un segfault, o alcuni altri problemi che non posso testare prima di eseguirlo. So che la libreria C standard ha funzioni di gestione del segnale, ma non so come usarle per gestire il problema per evitare la terminazione del programma (suppongo, non posso semplicemente saltare alla posizione prima dell'esecuzione delle funzioni problematiche o posso?). In Windows potrei usare i gestori di eccezioni SEH, ma non posso farlo con Linux o con qualsiasi altro SO. Per quanto riguarda l'utilizzo del mio gestore di eccezioni per gestire questi problemi, quanto è diverso tra Windows/Linux? Sarebbe anche possibile (tramite assemblatore - diciamo solo sulla piattaforma x86)?Gestione delle eccezioni CPU in C++

Sto chiedendo per lo più per curiosità, non sto cercando di risolvere un problema esistente (ancora). Grazie

+0

Questo può essere di interesse: http://stackoverflow.com/questions/4747934/c-catch-a-divide-by-zero-error –

+1

mentre in caso di un segfault non si può fare nulla, io devo ammettere la divisione per zero, i casi di overflow e underflow mi hanno sempre colpito come probabilità e sarebbe bello riuscire a catturarli. –

risposta

5

libsigsegv è una libreria multipiattaforma per la gestione degli errori di segmentazione e degli overflow dello stack. Tuttavia, nella grande maggioranza dei casi, quando si rileva un errore di segmentazione, la cosa giusta da fare è terminare l'esecuzione il più velocemente possibile invece di provare a recuperarla. Un segfault è di solito indicativo di un bug o di una memoria corrotta, e una volta che si è danneggiata la memoria, è praticamente impossibile recuperarla.

+0

Sì, una soluzione del genere sarebbe applicabile solo a pochi casi, in cui posso garantire che l'ambiente del programma non fosse altrimenti danneggiato. –

+0

@ John Holecek Come si può fornire tale garanzia in qualsiasi circostanza? –

+0

Ad esempio per verificare se un valore del puntatore punta a una posizione di memoria valida - una cosa del genere può essere utile per un garbage collector di qualche tipo. –

2

Il problema è che se il plug-in seg fallisce, non è possibile garantire quale stato sarà il tuo programma principale sarà più in. Anche se potessi prendere SIGSEGV (che credo tu possa) non avresti un buon modo per recuperare nella tua applicazione.

Quello che dovresti fare è eseguire il plugin in un processo di fork in modo che se si blocca il tuo programma principale non viene rimosso. Ad esempio, è possibile comunicare tra i processi con una pipe.

+0

L'esempio con il plugin era solo un'idea in cui poteva essere usato. Tale plugin dovrebbe essere eseguito come sottoprocesso, come suggerito o dovrebbe seguire un rigido insieme di regole, come potrebbe o non potrebbe fare (ma ancora una volta, non sarei in grado di far rispettare Questo). Tuttavia nel caso in cui ho solo bisogno di leggere/scrivere in qualche memoria, dovrei essere in grado di recuperare in caso di segfault. –

+0

Sì, sarebbe generalmente una cosa complicata da fare –

1

No, non esiste un modo standard. In C++, tali "eccezioni CPU" sono manifestazioni di Undefined Behaviour, cioè lo standard C++ non specifica nulla sul loro comportamento, o su tutto ciò che accade in seguito. Anche la nozione di "segfault" non esiste nel C++ standard. Dereferenziare un puntatore NULL potrebbe incendiare il tuo computer, e ovviamente a quel punto c'è ancora poco da catturare.

C non ha risolto neanche questo: SIGSEGV non è un segnale C standard; è un'estensione POSIX. Windows non ha SIGSEGV, per esempio.

2

Questo non è coperto in Standard C++, tuttavia i sistemi operativi desktop comuni forniscono funzionalità per farlo. Windows dispone di Structured Exception Handling (SEH) per cui sono disponibili estensioni del compilatore pertinenti e POSIX offre la gestione dei segnali.

In genere, direi che non dovresti rilevare le eccezioni della CPU, si verificano solo se il tuo programma è in errore e, a quel punto, è il momento di decifrare un debugger, non continuare.

Non è possibile utilizzare lo stesso approccio, anche in assembler. Queste funzioni sono fornite dal sistema operativo- quando la CPU solleva un'eccezione, passa al sistema operativo per decidere cosa fare in merito, non in modalità utente. Non solo, ma direi che SEH e la gestione del segnale sono abbastanza diversi da giustificare approcci fondamentalmente diversi quando li si utilizza in codice, quindi un semplice #ifdef non lo taglierà.

setjmp e longjmp possono funzionare solo per "segnali" generati dal codice in modalità utente, non a livello di SO.

0

gestori di segnale può sistemare l'esecuzione del programma a un certo punto; ciò che è permesso è documentato nella pagina di manuale del segnale (7).

ci sono implementazioni che saranno

  • ritorno alle istruzioni ha provocato l'errore da gestori SIGSEGV (questo consente di modificare la mappa della memoria e ritorno), e

  • andare alle istruzioni seguenti del guasto per SIGFPE (quindi il gestore del segnale deve cercare le istruzioni e fornire un risultato)

Si noti che questa è l'implementazione- definito al meglio. Il manuale ti dice di non fare affidamento su nulla di tutto ciò. Sei stato avvertito. :)