2010-04-16 21 views
22

Questa è la rovina della mia esistenza di programmazione. Dopo aver distribuito un'applicazione, quando si verifica questo errore, nessuna quantità di dump di debug indica che l'oggetto WHAT non è stato istanziato. Ho lo stack delle chiamate, è grandioso, mi dice approssimativamente dove si trova l'oggetto, ma c'è un modo per far sì che .NET mi dica il vero nome dell'oggetto?Riferimento oggetto non impostato su un'istanza di un oggetto: come trovare il nome dell'oggetto in questione nell'eccezione?

Se li prendi mentre esegui il debug, ovviamente il programma si interrompe sulla creatura in questione, ma se succede dopo che il programma è in libertà, buona fortuna.

Ci deve essere un modo.

Ho esplorato le eccezioni restituite in questi casi e non c'è niente di utile.

+2

In realtà, questo è vero per un sacco di fastidiose eccezioni. Indice fuori portata un altro colpevole. "Indice fuori intervallo: " sarebbe di grande aiuto. – Jason

risposta

18

No, non è possibile. L'eccezione si verifica perché un riferimento è null e i riferimenti non hanno nomi. Variabili e membri di classe/struttura hanno nomi, ma non è sicuro che il riferimento sia memorizzato in uno di questi. Il riferimento potrebbe ad esempio essere creato in questo modo:

someObject.GetInstance().DoSomething(); 

Se il metodo restituisce il valore null GetInstance, c'è un'eccezione di riferimento null quando si tenta di utilizzare il riferimento per chiamare DoSomething. Il riferimento è solo un valore di ritorno dal metodo, non è memorizzato in una variabile, quindi non c'è nulla da cui ottenere un nome.

Se si dispone di informazioni di debug nell'assieme compilato, si otterrà il numero di riga nella traccia dello stack nell'eccezione, ma ciò è il più vicino possibile.

+0

Il numero di riga sarebbe di grande aiuto, ma la traccia dello stack non sembra includere il numero di riga quando il programma viene eseguito in modalità debug lontano dall'ambiente di sviluppo. – Jason

+4

@ Jason: Penso che sia necessario copiare il file PDB nel percorso del programma. Il file PDB è ciò che il debugger utilizza per mappare dalle posizioni nel codice compilato alle posizioni nei file di origine. – itowlson

+0

Ottima risposta @itowlson, risolto il mio problema –

0

Questo è uno di quei casi in cui è davvero necessario allegare all'applicazione e passare attraverso l'area generale del codice incriminato per capire da dove proviene tale riferimento null.

0

Penso che attualmente il meglio che è possibile ottenere è la linea no.

StackTrace: at test_003.Form1.button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\...\Projects\test_003\test_003\Form1.cs:line 52

Se fanno qualcosa in futuro su questo problema, sarebbe bello.

8

NullReferenceException è il più malvagio di tutte le eccezioni in un'applicazione. Significa che un riferimento potenzialmente non nullo non è stato verificato per un valore nullo prima che fosse acceduto.

È malvagio, perché il runtime non è in grado di determinare ciò che si aspettava di trovare nel riferimento, quindi non è in grado di dirti quale esattamente non è riuscito a de-referenziare.

Lo stack trace è l'unico amico in questa eccezione, in cui è possibile identificare almeno il metodo che ha generato l'eccezione. Se il tuo codice è abbastanza accurato, dovrebbe identificare una piccola quantità di codice da controllare.

Inoltre, se si sta eseguendo una build di debug e si hanno le informazioni di debug con gli assembly, si otterranno anche i numeri di riga di origine nello stack trace, in modo da poter sapere esattamente quale linea il metodo ha fallito.


La vera risposta è quello di evitare che questa eccezione da mai essere gettato.È un indicatore che alcuni codici sono stati scritti male, non riuscendo a gestire lo scenario in cui un riferimento era null.

Se si dispone di un metodo chiamato in cui è necessario fare qualcosa con un argomento di riferimento di tipo che ha bisogno di essere de-riferimento ad un certo punto, verificare la presenza di null e gettare ArgumentNullException, indicando il nome del parametro:

if(parameter == null) 
    throw new ArgumentNullException("parameter"); 

Se si sta eseguendo un'operazione all'interno di una classe e una proprietà impostabile può essere impostato per null, controllare prima di de-riferimento e gettare un InvalidOperationException che indica il problema:

if(Property == null) 
    throw new InvalidOperationException("Property cannot be null."); 

È inoltre necessario assicurarsi che tutti i metodi che si stanno chiamando in grado di restituire tipi di riferimento siano garantiti per restituire un valore. Per tutti quelli che non lo sono, effettuare controlli simili per null e gestire il caso in modo appropriato.

EDIT:

Per chiarire, non sto suggerendo che si esegue un controllo sulla ogni variabile di riferimento di tipo prima di de-riferimento di esso. Sarebbe una follia.

Si tratta di capire dove è possibile assegnare una variabile null e dove non può. Se si assegna un campo privato in una classe a un valore non nullo nel costruttore e il valore non viene mai assegnato nuovamente, non è necessario verificare se il valore è null; il design della tua classe ha fatto in modo che non possa mai essere.

Un oggetto ben progettato limiterà le opportunità per i valori null assegnati e utilizzerà il codice di protezione appropriato per generare eccezioni quando un valore null può essere presente.

+1

Sembra che molte infrastrutture lo impediscano, dal momento che quasi ogni oggetto è annullabile. Come gestisci questo quando hai centinaia di oggetti in un grande programma? Una sorta di codice automatico per impostare queste condizioni sarebbe perfetto. – Jason

+0

Si tratta di scrivere il codice di guardia dove è appropriato. Devi sapere che un valore non è nullo prima di de-referenziarlo. Se esiste la possibilità che possa essere nullo nell'esecuzione logica del codice, è necessario inserire del codice per gestire tali controlli. –

+1

@ Jason, Framework 4.0 ha un meccanismo per i Contratti di codice che può imporre il controllo nullo (e VS 2010 Premium o superiore verificherà anche in modo statico casi che potrebbero essere nulli). C'è una certa quantità di spese generali nell'impostazione dei Contratti, ma possono essere utili per altri casi pure. –

Problemi correlati