Frage
ich eher zufällig auf dieses Stück Code, das mir total gebrochen zu sein scheint, aber es kommt vor, dass this
null
ist. Bekomme ich nur nicht, wie dies null
werden kann
Es ist in einem normalen Methodenaufruf wie
myObject->func();
innen MyObject::func()
wir haben
if (!this) { return false; }
ist es eine Möglichkeit, die erste Zeile einen NullPointerException
haben kann stattdessen innerhalb des null
des Gehens zu werfen (?) Methode?
Lösung
Wenn Sie:
MyObject *o = NULL;
o->func();
Was passiert, hängt davon ab, ob func
ist virtuell. Wenn ja, dann wird es zum Absturz bringen, weil es um ein Objekt zu erhalten, die VTable aus braucht. Aber wenn es nicht virtuell ist der Anruf fährt mit dem diesem Zeiger auf NULL gesetzt.
Ich glaube, die Norm sagt, das „nicht definiertes Verhalten“ ist, so könnte alles passieren, aber typischer Compiler nur den Code generieren, um nicht zu prüfen, ob der Zeiger NULL ist. Einige bekannte Bibliotheken setzen auf das Verhalten, das ich beschrieben:. MFC hat eine Funktion, so etwas wie SafeGetHandle
genannt, die auf einem Null-Zeiger aufgerufen werden kann, und gibt NULL zurück, in diesem Fall
Sie möchten vielleicht eine wiederverwendbare Hilfsfunktion schreiben:
void CheckNotNull(void *p)
{
if (p == NULL)
throw NullPointerException();
}
Sie können dann verwenden, zu Beginn einer Funktion, alle ihre Argumente zu überprüfen, einschließlich this
:
CheckNotNull(this);
Andere Tipps
Eine Art und Weise zu stoppen diese Art von Fehlern (durch Design) wird mit einer Zeiger-Wrapper-Klasse (ähnlich ein shared_ptr
), die mit einem Null-Zeiger-Argumente bei der Erstellung wirft. Es kann auch werfen, wenn dereferenziert, aber das ist ein wenig zu spät -. Besser als gar nichts, ich denke
if(this == null)
throw new NullPointerException;
if(!this)
return false;
(dies == NULL) ist nicht definiertes Verhalten der Norm entsprechend. Ich denke, Sie sollten diese Prüfung entfernen:)
Angenommen, wir den folgenden Aufruf machen:
((CSomeClass*) 0)->method();
Das Verhalten ist bereits undefiniert, warum soll man den Scheck für diese == NULL tun in CSomeClass :: Methode?
EDITED: Ich gehe davon aus, dass Ihr Compiler (0 == this) behandelt, wenn Sie nicht Mitglied Variablen verwenden, aber wo würde es die virtuellen Tabellenzeiger finden? In diesem Fall können Sie Ihre Klasse nicht polymoprhism verwenden.
Es ist möglich, für this
null zu sein. Ich vermute, dass dieser Code versucht (schlecht) eine Race-Bedingung erkennen, wo sich das Objekt noch nicht initialisiert beendet wird oder gelöscht wurde.
Dieser Zeiger kann in solchen Fällen null werden:
class Test
{
public:
bool f();
private:
int m_i;
};
bool Test::f()
{
if(!this)
{
return false;
}
m_i = 0;
return true;
}
int main(int argc, char **argv)
{
Test* p = new Test;
delete p;
p = NULL;
p->f();
}
Ich denke, jemand einen schnellen Hack tat, um die Zugriffsverletzung Ausnahme zu vermeiden.
Dieses == null sollte nur auftreten, wenn Sie eine Methode auf ein gelöschtes Objekt aufgerufen wird, oder wenn etwas in den Speicher schreibt, dass es nicht (und die diesen Zeiger insbesondere des Objekts überschreiben).
Sie sollten untersuchen, was mit Ihrem Code wirklich falsch ist, anstatt zu versuchen um es so zu arbeiten.