Was passiert in C ++, wenn ich ein Objekt als Referenz übergebe und es den Gültigkeitsbereich verlässt?

8

Ich denke, diese Frage wird am besten mit einem kleinen Codeausschnitt gestellt, den ich gerade geschrieben habe:

%Vor%

Der Code kompiliert und läuft gut mit g ++:

%Vor%

Dies ist jedoch nicht das Verhalten, das ich erwartet habe. Ich habe beim zweiten Aufruf von fc->printFriend() einen Fehler erwartet. Ist mein Verständnis davon, wie die Weitergabe / Speicherung durch Referenz funktioniert nicht korrekt oder ist das etwas, das gerade in kleinem Maßstab funktioniert und würde wahrscheinlich in einer anspruchsvolleren Anwendung explodieren?

    
Corey D 29.09.2011, 21:56
quelle

5 Antworten

11

Es funktioniert genau wie für Zeiger: Verwenden von etwas (Zeiger / Verweis), das auf ein Objekt verweist, das nicht mehr existiert, ist undefiniertes Verhalten. Es scheint zu funktionieren, aber es kann jederzeit brechen.

Warnung: Im Folgenden wird kurz erläutert, warum solche Methodenaufrufe bei mehreren Gelegenheiten nur zu Informationszwecken funktionieren können. Wenn Sie tatsächlichen Code schreiben, sollten Sie sich nur darauf verlassen, was der Standard sagt

Was das Verhalten betrifft, das Sie beobachten: Bei den meisten (allen?) Compilern werden Methodenaufrufe als Funktionsaufrufe mit einem versteckten this -Parameter implementiert, der auf die Instanz der Klasse verweist, auf der die Methode ausgeführt werden soll. Aber in Ihrem Fall wird der this -Zeiger überhaupt nicht verwendet (der Code in der Funktion bezieht sich nicht auf ein Feld und es gibt keine virtuelle Verteilung), so dass der (jetzt ungültige) this -Zeiger nicht verwendet wird und der Anruf ist erfolgreich.

In anderen Fällen scheint es, dass es funktioniert, auch wenn es sich auf ein Objekt außerhalb des Gültigkeitsbereichs bezieht, weil sein Speicher noch nicht wiederverwendet wurde (obwohl der Destruktor bereits ausgeführt wurde, wird die Methode das Objekt wahrscheinlich in einem inkonsistenter Zustand).

Auch hier sollten Sie sich nicht auf diese Informationen verlassen. Sie sollen nur wissen lassen, warum dieser Anruf immer noch funktioniert.

    
Matteo Italia 29.09.2011, 21:59
quelle
12

Wenn Sie eine Referenz auf ein Objekt speichern, dessen Lebensdauer abgelaufen ist, ist der Zugriff darauf nicht definiert. So kann alles passieren, es kann funktionieren, es kann scheitern, es kann abstürzen, und wie es scheint, kann ich sagen, dass es eine Pizza bestellen kann.

    
K-ballo 29.09.2011 21:59
quelle
1

Undefiniertes Verhalten. Per Definition können Sie keine Annahmen darüber treffen, was passieren wird, wenn dieser Code ausgeführt wird. Der Compiler löscht möglicherweise nicht den Speicher, in dem sich bc noch befindet, aber Sie können nicht darauf zählen.

Ich habe den gleichen Fehler in einem Programm bei der Arbeit einmal behoben. Bei Verwendung des Compilers von Intel wurde die Variable, die den Gültigkeitsbereich verlassen hatte, noch nicht "bereinigt", so dass der Speicher immer noch "gültig" war (das Verhalten war jedoch nicht definiert). Der Compiler von Microsoft hat es jedoch aggressiver aufgeräumt und der Fehler war offensichtlich.

    
Ed S. 29.09.2011 21:59
quelle
1

Sie haben eine freie Referenz, was zu undefiniertem Verhalten führt.

    
Fred Larson 29.09.2011 21:59
quelle
1
  1. siehe hier: Kann auf den Speicher einer lokalen Variablen außerhalb ihres Gültigkeitsbereichs zugegriffen werden?

  2. Es wird fast funktionieren, da Sie keine virtuellen Funktionen haben und Sie nicht auf Felder von BasicClass zugreifen: Alle Methoden, die Sie aufrufen, haben eine statische Bindung, und 'this' wird nie benutzt. Sie greifen also nie auf "nicht belegten Speicher" zu.

Ivan 29.09.2011 22:22
quelle

Tags und Links