Was passiert, wenn ich eine Member-Funktion für einen NULL-Objektzeiger aufrufe? [duplicate]

Lesezeit: 6 Minuten

Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Rajendra Uppal

Als Interviewfrage wurde mir folgendes gestellt:

class A
{
public:
    void fun()
    {
        std::cout << "fun" << std::endl;
    }
};

A* a = NULL;
a->fun();

Was passiert, wenn dieser Code ausgeführt wird, und warum?


Siehe auch:

  • Wann führt das Aufrufen einer Memberfunktion für eine Nullinstanz zu undefiniertem Verhalten?

  • Undefiniertes Verhalten. Oder wenn der Code als komplette Einheit wörtlich zu nehmen ist, ein Kompilierungsfehler.

    anon

    28. März 2010 um 15:48 Uhr


  • Schwierige Frage oder Fangfrage? Es wird nicht kompiliert, weil Class (Großbuchstabe C) ist kein C++-Schlüsselwort.

    – Ken

    28. März 2010 um 15:49 Uhr

  • @ duffymo, ich habe es überprüft und es druckt “Spaß” und ich konnte nicht herausfinden warum, also habe ich hier gefragt.

    – Rajendra Uppal

    28. März 2010 um 16:00 Uhr

  • @Rajendra Es spielt keine Rolle, was es tut, wenn Sie es mit Ihrem spezifischen Compiler kompilieren. Der C ++ – Standard besagt, dass das Dereferenzieren eines Nullzeigers nicht definiert ist. Die nächste Iteration Ihres Compilers oder eines anderen Compilers könnte also etwas anderes tun, aber ebenso undefiniert.

    anon

    28. März 2010 um 16:03 Uhr

  • Wie ist das “tricky”? Es ist einfach und, wenn Sie mich fragen, ziemlich sinnlos. Zeiger erzeugen, auf NULL initialisieren und gleich in der nächsten Zeile verwenden – wie “typisch”!

    – Daniel Daranas

    28. März 2010 um 16:08 Uhr


Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
etw

Es ist ein undefiniertes Verhalten, also kann alles passieren.

Ein mögliches Ergebnis wäre, dass es nur druckt "fun" da die Methode auf keine Mitgliedsvariablen des Objekts zugreift, für das sie aufgerufen wird (auf den Speicher, in dem sich das Objekt angeblich befindet, muss nicht zugegriffen werden, sodass Zugriffsverletzungen nicht unbedingt auftreten).

  • @Kamal Wenn die Funktion nicht virtuell ist, wird sie statisch verknüpft. Kein Bedarf für einen Tisch. Keine Notwendigkeit für den Objektzeiger.

    – Frank Krüger

    28. März 2010 um 16:13 Uhr

  • @Kamal Der Compiler könnte statische Informationen verwenden (er weiß, dass der Zeiger vom Typ A ist), um die Funktion zu finden. Die Tatsache, dass der Compiler dies tun kann, bedeutet, dass er dies tun muss, und verhindert nicht, dass dies ein undefiniertes Verhalten ist.

    anon

    28. März 2010 um 16:13 Uhr


  • @Kamal: Wer hat gesagt, dass es gespeichert werden muss? Der Compiler kann den Funktionsaufruf umwandeln in A::fun(a).

    – kennytm

    28. März 2010 um 16:14 Uhr

  • @Kamal: Der Compiler kennt den Typ des Objekts und die Adresse der Methode, die zur Kompilierzeit aufgerufen werden soll, und kann diese Adresse “fest codiert” einfügen. Zur Laufzeit muss nichts nachgeschlagen werden. (Damit ist nicht der Compiler gemeint hat es so zu machen, aber es könnte.)

    – etw

    28. März 2010 um 16:14 Uhr


  • Das Objekt qualifiziert sich als POD, daher glaube ich nicht, dass der Compiler versteckte Felder im Objekt haben darf, die zum Auffinden von Elementfunktionen verwendet werden sollen. Insofern wäre es sehr überraschend, wenn der Compiler nicht die richtige Member-Funktion finden könnte. Aufgrund der Lebensdauerregeln für POD-Typen ist es nicht einmal erlaubt, eine Nachschlagetabelle zu haben, die Objektzeiger auf Mitgliedsfunktionen abbildet. Hier gibt es sehr wenig Flexibilität bei der Auflösung von Memberfunktionen. Die Tatsache, dass dies ein undefiniertes Verhalten ist, ermöglicht es dem Compiler wirklich, eine explizite Nullprüfung einzufügen, um das Debuggen zu unterstützen.

    – Ben Voigt

    2. Juli 2013 um 5:11 Uhr

Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Daniel Goldberg

Nach dem Standard ist dies ein undefiniertes Verhalten und daher eine sehr schlechte Sache. In der Realität der meisten Programmierplattformen (sowohl auf X86 als auch auf mehreren anderen Architekturen) wird dies problemlos funktionieren.

Warum? Überlegen Sie, wie Klassenfunktionen in C++ implementiert werden. Dies ist keine virtuelle Funktion, daher kann dies ein statischer Aufruf an eine bekannte Adresse sein. In der x86-Assembly können wir dies als sehen

mov A, 0
mov ecx, A
call a__fun

Da a__fun keine Instanzdaten benötigt, wird nichts passieren, obwohl es einen null this-Zeiger erhält.

Immer noch beschissener Code und jeder Compiler wird schreien, aber er kann laufen.

  • Ja, das ist undefiniertes Verhalten. Ja das dürfen wie erwartet auf einer bestimmten Architektur ausgeführt werden. Es ist jedoch ratsam, immer die folgende Weisheit im Hinterkopf zu behalten: “Das schlimmste Ergebnis eines undefinierten Verhaltens ist, dass es das tut, was Sie erwartet haben.”

    – dgnuff

    26. Juni 2018 um 20:18 Uhr


  • Diese Antwort ignoriert alle “Optimierungen”. Wenn der Compiler sehen kann, dass der Zeiger null ist, kann er den Aufruf einfach vollständig unterdrücken. Sie konzentrieren sich zu sehr auf die Details auf niedriger Ebene darüber, was mit dem Anruf passiert wenn es passiert. Aber es gibt einen Grund, warum wir es undefiniert nennen. Das ist nicht dasselbe wie “im Grunde funktioniert”.

    – Asteroiden mit Flügeln

    23. April 2020 um 13:59 Uhr

1647168610 886 Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Ken Bloom

Das wahrscheinlichste Verhalten auf den meisten modernen Computern ist, dass es läuft und “Spaß” druckt, weil:

  • C++ prüft nicht, ob der Zeiger NULL ist, bevor die Funktion aufgerufen wird
  • fun() ist nicht virtuell, daher besteht keine Notwendigkeit, auf eine vtable zum Aufrufen zu verweisen fun()
  • fun() Greifen Sie niemals auf Member-Variablen in zu A Es muss also die Null nicht dereferenziert werden this Zeiger.

  • 3. A* a = NULL; a->fun(); außerhalb eines Funktionsgremiums illegal ist.

    – sepp2k

    28. März 2010 um 15:51 Uhr

  • Aber ich denke, wir können immer noch unseren Verstand beugen und irgendwie verstehen, was er meinte

    – henle

    28. März 2010 um 15:54 Uhr

1647168611 866 Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Johannes Schaub – litb

Wir können nicht wissen, was Wille. Alles kann passieren, weil das Programm undefiniertes Verhalten zeigt. Siehe Führt das Aufrufen einer Member-Funktion für eine Nullinstanz zu undefiniertem Verhalten?.

1647168612 824 Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Benutzer97693321

Ich habe es mehrmals versucht, die ganze Zeit macht die Ausgabe “Spaß”, das liegt an der Funktion fun ist instanzunabhängig a. beim Anrufen a->fun(); a zeigt auf 0, also ist dies ein undefiniertes Verhalten, aber in den meisten Compilern sollte es keinen Absturz geben.

  • A* a = NULL; führt ausdrücklich nicht zu einem Konstruktoraufruf

    – Dennis Zickefoose

    29. Oktober 2011 um 21:04 Uhr

1647168612 264 Was passiert wenn ich eine Member Funktion fur einen NULL Objektzeiger aufrufe
Navin Maheshwari

Drei Punkte könnten helfen:

1) Alle Funktionen sind im Code- oder Textabschnitt gespeichert.

2) Nicht virtuelle Funktionen werden zur Complie-Zeit aufgelöst.

3) Beim Aufrufen von Memberfunktionen der Klasse übergeben wir das aktuelle Objekt als this Zeiger auf diese Funktion.

Kommen wir zu Ihrer Frage, hier fun() Funktion ist bereits im Speicher (Codeabschnitt / Textabschnitt). Als Funktion fun() nicht virtual ist, wird es zur Complie-Zeit aufgelöst (d. h. für diese Zeile springt es zur Anweisung X im Codeabschnitt mit this Zeiger als NULL). Da keine Member-Variable und keine virtuelle Funktion verwendet/aufgerufen werden fun() Funktion, es funktioniert einwandfrei.

  • A* a = NULL; führt ausdrücklich nicht zu einem Konstruktoraufruf

    – Dennis Zickefoose

    29. Oktober 2011 um 21:04 Uhr

997270cookie-checkWas passiert, wenn ich eine Member-Funktion für einen NULL-Objektzeiger aufrufe? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy