2013-01-03 17 views
19

Sia Java che C#, e probabilmente anche molti altri linguaggi, hanno una classe di eccezioni predefinita che viene generata quando viene utilizzato un parametro Null dove non dovrebbe. C'è qualcosa di simile in C++? Se no, c'è un'altra eccezione predefinita che posso usare o dovrei definire mia?Esiste un equivalente C++ di una NullPointerException

+9

Errore di segmentazione. – kmkaplan

+0

FTR, in C# non usi NullReferenceException per nulla a meno che tu non voglia essere pugnalato dai tuoi compagni di squadra. –

+0

In C# uso un ArgumentNullException e i miei compagni di squadra sono sempre gentili con me. –

risposta

20

Il dereferenziamento di un puntatore NULL è un comportamento non definito in C++, il che significa che il codice può sembrare funzionare. Non è garantita l'eccezione a un'eccezione. È possibile utilizzare l'eccezione

std::invalid_argument

(fornire un valore significativo per esso - "p is NULL"), ma si dovrà fare il check da soli.

+0

Grazie, questa è la risposta che stavo cercando. –

9

Di solito, in C++ (o C per quella materia), è mai dereference un puntatore NULL. Questo ha un comportamento non definito (probabilmente un segfault su qualsiasi implementazione che conosco, ma qualsiasi cosa potrebbe accadere secondo lo standard). Probabilmente è una brutta cosa anche in altre lingue, ma non ne conosco abbastanza per affermarlo.

È meglio prevenire la situazione piuttosto che provare a recuperare da esso (che non può essere fatto in C o C++ comunque).

Lo schema usuale per evitare alcuni errori programmatore è quella di impiegare assert() all'interno organi funzionali quali:

int foo(int* myint) 
{ 
    // Ensure myint is not NULL 
    assert(myint); 

    // Do something with myint 
    (*myint)++; 

    return *myint; 
} 

Tali assert() chiamate sono completamente ignorate build di rilascio e quindi non hanno costi di produzione. Aiutano solo lo sviluppo. Su build di debug e se la condizione non viene soddisfatta, il programma si interrompe immediatamente con un messaggio di errore molto esplicito. Eseguendolo attraverso un debugger, puoi facilmente controllare lo stack di chiamate per indagare per il motivo esatto.

+5

Aditamente in C# in Java è anche una cattiva pratica affidarsi alla cattura di puntatori nulli (solo l'eccezione è recupero di livello molto alto da tutte le eccezioni di runtime, ad esempio in un pool di thread). Sono pensati per rendere più facile trovare errori di programmazione. – Thirler

+0

Tieni presente che l'assert() sarà # ifdef'dout se il codice viene compilato con NDEBUG definito (-DNDEBUG). – daddesio

4

FTR, in C# non si usa NullReferenceException s per nulla a meno che non si voglia essere pugnalati dai compagni di squadra. C'è un ArgumentNullException invece di rifiutare argomenti nulli. Le NRE sono pensate per essere lanciate dal runtime, non tu.

Ma nota che in realtà non c'è alcun vantaggio su questa affermazione perché non dovresti prendere uno di questi: se vengono lanciati, indicano un bug. Questi sono quelli che Eric Lippert chiama boneheaded exceptions e sono un vero peccato, e non c'è niente che il tuo codice dovrebbe fare specificamente con loro.

2

In caso di dereferenziazione C++, il puntatore nullo si tradurrà in un comportamento indefinito, cosa che per lo più termina con l'errore di segmentazione. In Visual Studio è possibile utilizzare estensioni come Structured Exception Handling (SEH), che consentono di catturare il dereferenziamento del puntatore nullo.

2

In quasi tutti i casi che implicano l'utilizzo errato di un puntatore nullo (in particolare, la disattivazione), lo standard C++ lascia semplicemente il comportamento indefinito. Non viene fornito alcun tipo di eccezione specifico (e non verrà generata alcuna eccezione).

Una possibile eccezione a questa regola viene in mente, però.std::function, che è un modello standard-libreria C++ 11 che può essere usato per avvolgere le funzioni, può essere assegnato un puntatore nullo:

std::function<void(int)> func = nullptr; 

E se poi si effettua un tentativo di chiamare la funzione avvolto da essa per facendo func(arg); per qualche argomento arg, verrà generata un'eccezione std::bad_function_call.

Ovviamente, questo non è completamente equivalente alle eccezioni del puntatore nullo di altre lingue, poiché è molto meno generalmente applicabile.

5

Non esiste un'eccezione standard in C++ per il dereferenziamento di un puntatore NULL.

Se lo si desidera, è possibile implementarlo da soli. Su UNIX, imposta un gestore di segnale SIGSEGV e genera un'eccezione dal gestore. Su Windows, usa l'API _set_se_translator() per installare un gestore "Eccezione strutturata".

Problemi correlati