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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top