Domanda

Sto osservando un po 'di codice (Delphi 7) con il seguente controllo è in cima a ogni chiamata di metodo per un oggetto specifico:

if not Assigned(self) then
  raise Exception.CreateRes(@sAbstractError);

  { Real code for this method}

Suppongo che questo mi impedirebbe di provare a chiamare un metodo su un puntatore a oggetto null. Ma otterrei un'eccezione non appena provassi ad accedere ai dati dei membri in quel caso, giusto?

È questo un tipo di standard che non ho mai visto prima? L'oggetto in questione deriva da TPersistent.

È stato utile?

Soluzione

Puoi chiamare un metodo di istanza su un puntatore null anche se non è il tipo di cosa che vuoi fare deliberatamente. Quando ciò accade, l'esecuzione continua abbastanza felicemente fino a quando non deve accedere ai dati dell'istanza e poi va tutto bene.

In tal caso, il controllo di zero ti avviserebbe all'inizio della procedura in modo da poter fare qualcosa di diverso come la registrazione di una traccia dello stack. Oppure potresti mettere un punto di interruzione sulla linea di rilancio in modo da poter tuffarti e vedere cosa sta succedendo.

Vale a dire, è qualcosa che potrei fare se avessi un bug specifico che stavo cercando di rintracciare dove veniva usato un riferimento zero.

Farlo regolarmente mi sembra un odore di codice.

Altri suggerimenti

Un chiaro errore che si lamenta di un puntatore zero è meglio di una violazione di accesso che non dice come sia successo.

Esistono scenari di violazione dell'accesso che possono causare l'esecuzione di codice in memoria in cui Self è zero. Alcuni programmatori, invece di risolvere il vero problema, cercano di aggirare usando tali asserzioni, per prevenire una sorta di corruzione. Verificherei molto bene se quell'eccezione aumenterà mai in fase di esecuzione, in tal caso - hai un codice difettoso sotto le tue mani.

Puoi leggere il seguente articolo sull'argomento: When Self in Nil ... You Know Sei nei guai .

Un'altra possibilità è legata agli eventi, puoi leggere di più qui, con molti esempi per tali test e spiegazioni corrispondenti: Eventi multicast - Parte 2 .

Questa è un'occasione che dovrebbe sicuramente portare a un arresto anomalo (ovvero un'eccezione del sistema operativo come "letto dall'indirizzo 0x00000000"). Generare un'eccezione linguistica è semplicemente ridondante (e l'uso improprio di EAbstractError qui non lo rende migliore).

Il controllo di parametri di input validi non è un'attività fattibile in un linguaggio non sicuro, poiché non otterrai mai la certezza, e quindi la tua gestione di parametri non validi non sarà mai coerente. (Perché si genera un'eccezione quando viene passato un puntatore zero, ma non per 0x00000001, che non è altrettanto valido?). Per una discussione più tecnica di questa domanda, leggi il blog di Larry Osterman su perché non controllare i puntatori validi .

Va ??notato un'eccezione: in Delphi, il metodo Free può essere chiamato su un puntatore zero, che ovviamente richiede quel tipo di controllo.

E poi c'è sempre la possibilità che il codice non si blocchi durante l'esecuzione con zero Self. Esempio: se non accede a nessun campo dell'oggetto proprietario. In tal caso, questo test rileverà il problema che altrimenti non verrebbe rilevato.

Tuttavia, questo sta portando la programmazione difensiva all'estremo. Non lo faccio mai (OK, quasi mai - solo quando sto cacciando i conigli ... errr ... squashing bugs).

Sembra che l'intenzione originale per quel metodo sia quella di diventare un metodo astratto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top