Come catturare l’eccezione del puntatore nullo?

try { int* p = 0; *p = 1; } catch (...) { cout << "null pointer." << endl; } 

Ho provato a catturare l’eccezione come questa ma non funziona, nessun aiuto?

Non esiste nulla come “eccezione puntatore null” in C ++. Le uniche eccezioni che puoi cogliere sono le eccezioni lanciate esplicitamente dalle espressioni di throw (più, come notava Pavel, alcune eccezioni standard di C ++ lanciate intrinsecamente dall’operatore standard operator new , dynamic_cast ecc.). Non ci sono altre eccezioni in C ++. Dereferenziare i puntatori nulli, la divisione per zero ecc. Non genera eccezioni in C ++, produce un comportamento indefinito . Se si desidera che le eccezioni vengano generate in casi del genere, è responsabilità dell’utente rilevare manualmente tali condizioni e eseguire esplicitamente il throw . È così che funziona in C ++.

Qualunque cosa tu sembri cercare non ha a che fare con il linguaggio C ++, ma piuttosto una caratteristica di un’implementazione particolare. In Visual C ++, ad esempio, le eccezioni di sistema / hardware possono essere “convertite” in eccezioni C ++, ma c’è un prezzo collegato a questa funzionalità non standard, che normalmente non vale la pena pagare.

Non puoi. De-referenziare un puntatore nullo è una cosa di sistema.

Su Linux, il SO solleva i segnali nella tua applicazione. Dai un’occhiata a csignal per vedere come gestire i segnali. Per “catturare” uno, si agganci una funzione in quella che verrà chiamata nel caso di SIGSEGV . Qui puoi provare a stampare alcune informazioni prima di terminare con grazia il programma.

Windows utilizza la gestione delle eccezioni strutturate . È ansible utilizzare le istruzioni __try/__except , come indicato nel collegamento precedente. Il modo in cui l’ho fatto in una certa utilità di debug che ho scritto era con la funzione _set_se_translator (perché combacia strettamente con gli hook). In Visual Studio, assicurati di avere triggersto SEH. Con questa funzione, è ansible colbind una funzione per chiamare quando il sistema solleva un’eccezione nell’applicazione; nel tuo caso lo chiamerebbe con EXCEPTION_ACCESS_VIOLATION . È quindi ansible generare un’eccezione e farla propagare di nuovo come se fosse stata generata un’eccezione in primo luogo.

Dereferenziare un null (o un puntatore che è passato alla fine della matrice o un puntatore non valido casuale) provoca un comportamento indefinito. Non c’è un modo portatile per “catturarlo”.

C’è un modo molto semplice per catturare qualsiasi tipo di eccezione (divisione per zero, violazione di accesso, ecc.) In Visual Studio usando i blocchi try -> catch (...) .

Un piccolo aggiustamento del progetto è sufficiente. Basta abilitare l’opzione /EHa nelle impostazioni del progetto. Vedere Proprietà progetto -> C / C ++ -> Generazione codice -> Modifica le eccezioni Abilita C ++ su “Sì con eccezioni SEH” . Questo è tutto!

Vedi i dettagli qui: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

C ++ non esegue il controllo puntatore (anche se suppongo che alcune implementazioni potrebbero). Se si tenta di scrivere su un puntatore nullo, è molto probabile che si verifichi un arresto anomalo. Non genererà un’eccezione. Se vuoi prenderlo devi controllare tu stesso il valore del puntatore prima di provare a scrivere su di esso.

Generalmente non puoi. Anche se potessi, sarebbe come cercare di mettere un cerotto su un sottomarino che è saltato fuori.

Un’applicazione danneggiata può fare molto più danni di una che si è schiantato. Il mio consiglio qui sarebbe di lasciarlo in crash, quindi correggere il motivo per cui è andato in crash. Risciacquare. Ripetere.

Come altri hanno già detto, non puoi farlo in C ++.

Se posso fare un punto più ampio: anche in una lingua che ti permette di catturarlo, l’azione migliore è quella di non toccare i puntatori nulli. Catturare un errore quando è già esploso in faccia, quindi decidere di andare avanti come non è successo, non è una buona strategia di codifica. Cose come la dereferenziazione del puntatore nullo, l’overflow dello stack, ecc., Dovrebbero essere viste come eventi catastrofici e evitate difensivamente, anche se il tuo linguaggio ti consente di reactjs in modo diverso.

Non esiste un modo indipendente dalla piattaforma per farlo. Sotto Windows / MSVC ++ puoi usare __try / __ tranne

Ma non lo consiglierei di farlo comunque. Quasi certamente non è ansible ripristinare correttamente da un errore di segmentazione.

Se lo volessi, potresti semplicemente controllare il puntatore e lanciare …

 if (p == nullptr) throw std::exception("woot! a nullptr!") p->foo(); 

quindi questo sarebbe solo per il debug del problema, il nullptr non dovrebbe verificarsi in primo luogo 🙂

Risposta breve: non è ansible in un modo portatile o standard, poiché i bug di questo tipo sono potenzialmente in grado di corrompere il processo stesso.

Risposta lunga: puoi fare più di quanto tu possa pensare, e sicuramente più del default del programma che si blocca. Tuttavia, è necessario tenere a mente 3 cose:
1) Questi bug sono PIÙ gravi delle eccezioni e spesso non possono presentare eccezioni alla tua logica.
2) Il rilevamento e la gestione della libreria saranno dipendenti dalla piattaforma sul back-end, anche se è ansible fornire un’interfaccia astratta e pulita per il consumo pubblico.
3) Ci saranno sempre alcuni crash che sono così brutti che non puoi nemmeno rilevarli prima della fine.

Fondamentalmente, errori come segfaults o il danneggiamento dell’heap non sono eccezioni perché stanno corrompendo il processo reale che esegue il programma. Qualunque cosa tu abbia codificato nel programma è parte del programma, inclusa la gestione delle eccezioni, quindi qualsiasi cosa che non sia la registrazione di un bel messaggio di errore prima che il processo muoia è sconsigliabile nei pochi casi in cui non è imansible. In POSIX, il sistema operativo utilizza un sistema di segnalazione per segnalare errori come questi ed è ansible registrare le funzioni di callback per registrare l’errore prima di uscire. In Windows, il sistema operativo può a volte convertirli in eccezioni dall’aspetto normale da cui è ansible recuperare e recuperare.

Alla fine, comunque, la tua migliore scommessa è codificare difensivamente contro tali incubi. Su qualsiasi sistema operativo ci saranno alcuni che sono così cattivi che non è ansible rilevarli, anche in linea di principio, prima che il processo muoia. Ad esempio, corrompendo il proprio puntatore dello stack è qualcosa che può causare un crash così grave che persino i tuoi callback del segnale POSIX non lo vedono mai.

In VC ++ 2013 (e anche nelle versioni precedenti) puoi inserire punti di interruzione sulle eccezioni:

  1. Premi Ctrl + Alt + Canc (si aprirà la finestra di dialogo delle eccezioni).
  2. Espandi “Eccezioni Win32”
  3. Assicurarsi che l’eccezione “0xC0000005 Violazione di accesso” sia selezionata.

Ora esegui di nuovo il debug, un punto di interruzione verrà colpito esattamente quando si è verificata la dereferenza nulla.

Non esiste alcuna eccezione di puntatore NULL in c ++ ma si vuole comunque catturare lo stesso, quindi è necessario fornire la propria implementazione di class per lo stesso.

di seguito è riportato l’esempio per lo stesso.

 class Exception { public: Exception(const string& msg,int val) : msg_(msg),e(val) {} ~Exception( ) {} string getMessage( ) const {return(msg_);} int what(){ return e;} private: string msg_; int e; }; 

Ora basato sul controllo del puntatore NULL può essere lanciato come, throw(Exception("NullPointerException",NULL)); e sotto c’è il codice per catturare lo stesso.

  catch(Exception& e) { cout << "Not a valid object: " << e.getMessage( )<< ": "; cout<<"value="<