Der this-Zeiger im if



  • Was aber auch eine mehr als fragwürdige Praxis ist. 😉



  • dd++ schrieb:

    es gibt auch Klassen, die registrieren ihren this Zeiger im Konstruktor einer globalen Liste und tragen sich im Destruktor wieder aus. demzufolge kann man den this Zeiger auch auf Plausibilität prüfen und bei Fehler ein return false machen ... nur so als Beispiel ...

    Lol. Gibt auch Klassen, die haben auch einfach nur ein bool valid; das im Konstruktor auf true und im Destruktor auf false gesetzt wird. ... nur so als Beispiel ...



  • dd++ schrieb:

    es gibt auch Klassen, die registrieren ihren this Zeiger im Konstruktor einer globalen Liste und tragen sich im Destruktor wieder aus.

    Sicher, aber was hat das mit diesem Fall zu tun?

    demzufolge kann man den this Zeiger auch auf Plausibilität prüfen und bei Fehler ein return false machen ... nur so als Beispiel ...

    Das kann man zwar, aber bereits der Aufruf der Methode (bzw. das vorher stattfindende Dereferenzieren des null-Zeigers) ist UB, auch wenn sich das bei nicht-polymorphen Klassen in gängigen Implementationen tatsächlich so äußert, dass der this-Zeiger null ist und die Methode davon abgesehen normal aufgerufen wird.



  • es geht darum, daß bei mir gelegentlich Meldungen im Bugzilla gelandet sind, die daher kommen, daß jemand meine Methode mit einem Nullpointer aufgerufen hat. bei einer virtuellen Methode kommt er gar nicht erst in meine Methode hinein und es knallt beim Aufrufer. bei einer nichtvirtuellen Methode kann ich solange (wohldefiniert und nicht implementierungsabh.) in der Methode arbeiten, wie der this Zeiger nicht dereferenziert wird. und wenn ich dann entsprechend reagiere, landet der Bugzilla Eintrag mit dem coredump wieder beim Aufrufer



  • dd++ schrieb:

    es geht darum, daß bei mir gelegentlich Meldungen im Bugzilla gelandet sind, die daher kommen, daß jemand meine Methode mit einem Nullpointer aufgerufen hat.

    Wenn du solche User hast und sich niemand über die Performanceverluste stört, kann man da nichts machen (ausser auf eine DAU-Programmiersprache wie Java wechseln).

    Das ändert aber nichts daran, dass das kein "korrektes C++" ist, sondern so etwas wie ein UB-Detektions-Hack, der zufällig funktioniert.



  • erklär das mal dem Projektleiter: "laut ISO/IEC 14882 dürfte das eigentlich gar nicht passieren"



  • zur Ergänzung hier noch die entsprechenden Stellen aus dem ISO/IEC 14882:

    5.2.2 Function call
    4 When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. If the function is a non-static member function, the this parameter of the function (9.3.2) shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion (5.4).

    9.3.2 The this pointer [class.this]
    1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called.



  • dd++ schrieb:

    5.2.2 Function call
    4 When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. If the function is a non-static member function, the this parameter of the function (9.3.2) shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion (5.4).

    9.3.2 The this pointer [class.this]
    1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called.

    Wo steht da, dass this==0 UB ist?

    (Du bist auf der richtigen Spur, aber es fehlt noch der zwingende Beweis)



  • Na irgendwo steht bestimmt auch noch geschrieben, dass kein Objekt an der Objekttypsezifischen Adresse 0 zu finden sei. Das heißt, wenn this == 0, dann kann da kein Objekt sein für das die Methode aufgerufen wurde und this soll aber auf "das" Objekt zeigen laut 5.5.2.

    Irgendwie so?



  • ➡

    4.10 Pointer conversions [conv.ptr]
    1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type.



  • Hrmmm, ich weiß nicht ob daraus allein schon hervor geht, dass da nicht auch ein Objekt sein darf.



  • #include <iostream> 
    using std::cout; 
    
    struct Test{
    	void bla(){
    		cout << "bla\n";
    	}
    };
    
    int main(){
    	Test *t = 0;
    	t->bla();
    }
    

    Das ist UB? Für mich sieht das wir korrektes C++ aus, aber ich lese auch den Standard nicht.



  • Decimad schrieb:

    Hrmmm, ich weiß nicht ob daraus allein schon hervor geht, dass da nicht auch ein Objekt sein darf.

    ich denke mal, wenn da steht "null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type", dann darf da kein Objekt sein. es gibt ja auch z.B. bei op new und op delete spezielle Regeln für Nullpointer, die nur dann funktionieren, wenn der Nullpointer per Def. ungültig ist



  • nwp3 schrieb:

    Das ist UB? Für mich sieht das wir korrektes C++ aus, aber ich lese auch den Standard nicht.

    Sieht folgender Code für dich auch korrekt aus?

    Test* t = nullptr;
    funktion(*t);
    

    Wie stehts mit diesem?

    Test* t = nullptr;
    (*t).funktion();
    


  • Ich liebe Rätsel! Wie steht es mit

    struct A { void f () { } };
      int main ()
      {
        A* ap = 0;
        ap->f ();
      }
    

    ?



  • @Nexus & @beispiellos
    Sieht beides nach korrektem C++ ohne UB aus.



  • Welches Verhalten erwartest du denn bei der Dereferenzierung eines Nullzeigers?



  • @nwp3: Jackpot! Das Beispiel habe ich von hier, mit Kommentar vom Komitee.

    Eine Referenz auf 0 ist nicht per se UB, erst wenn auf sie irgendwie zugegriffen wird.

    Also ist es vollkommen richtig, this auf 0 zu testen und erst nachher darauf zuzugreifen 😮



  • Aus meiner Praxis: Ich lasse goto einmal im Jahr stehen. Ich lasse switch vielleicht zweimal im Jahr stehen. Aber eine Prüfung auf this==0 nicht einmal überhaupt.
    Ich fürchte, das muss man nur machen, wenn man das Gesamtkonzept verloren hat und versucht, Zugriffsfehler im Nachhinein an den Symptomen zu heilen.

    Ich stelle diesem Stil eine schlechte Prognose aus.



  • Nexus schrieb:

    Welches Verhalten erwartest du denn bei der Dereferenzierung eines Nullzeigers?

    Es gibt mit an Sicherheit grenzender Wahrscheinlichkeit einen Segfault, aber das ist nicht der Punkt. Das Programm wird von jedem korrekten C++-Compiler korrekt übersetzt und tut genau was da steht, einen Nullpointer dereferenzieren.
    Steht denn im Standard dass man den Nullpointer nicht dereferenzieren darf? Was wenn ein Mikrokontroller sein bisschen RAM bei 0 anfangen lässt und darauf hardwaretechnisch auch zugreifen kann, dürfte man das laut Standard trotzdem nicht?


Anmelden zum Antworten