Warum stürzt der folgende Code nicht ab, obwohl ich das Objekt gelöscht habe?

7
%Vor%

BEARBEITEN : Gurus, ich bin verwirrt von vielen der Aussagen "es kann abstürzen oder nicht" .. warum gibt es nicht einen Standard zu sagen, dies, wie wir mit einem Block von Speicher umgehen, die gelöscht wird mit "löschen Operator" ..? Irgendwelche Eingaben?

    
Warrior 17.06.2009, 10:25
quelle

10 Antworten

10

Weil es nach dem Compiler tatsächlich so aussieht, ist etwa so:

%Vor%

Da Sie "this" nicht berühren, greifen Sie nicht auf schlechten Speicher zu.

Obwohl das zweimalige Löschen von p einen Absturz verursachen könnte:

Ссылка

    
Srekel 17.06.2009, 10:29
quelle
7

Weil die Funktion nichts mit den Mitgliedsdaten des Objekts oder dem this Zeiger tut.

Es ist so, als würde man eine Funktion aufrufen

%Vor%

mit einem ungültigen Zeiger als self Argument.

Es gibt jedoch eine doppelte Löschung, die in einigen Umgebungen abstürzen kann.

    
laalto 17.06.2009 10:26
quelle
7

Löschen löscht nur die Speicherfreigabe und stellt sie dem Heap wieder zur Verfügung.

Der Wert des Zeigers ist nach dem Aufruf von delete undefiniert und kann daher nicht abstürzen.

Ein Programmiertipp, den ich verwende, um Programmierfehler zu reduzieren, besteht darin, nach einem Löschvorgang den Zeiger auf NULL zu setzen. Auf diese Weise wissen Sie, dass Sie nicht versehentlich einen Zeiger verwenden, nachdem dieser gelöscht wurde.

    
tschaible 17.06.2009 10:30
quelle
5

Sie können dasselbe mit Null-Zeigern tun, solange Sie niemals auf den Status der Klasseninstanz zugreifen:

%Vor%     
ralphtheninja 17.06.2009 10:36
quelle
5

Es ist sogar lustiger als das. Dies kompiliert & amp; läuft gut:

%Vor%

Auf die Shell:

%Vor%

:) Sie brauchen eigentlich kein Objekt, um diese Methode aufzurufen! Prost, h

    
haavee 17.06.2009 10:42
quelle
2

Selbst wenn der Methodenaufruf den This-Zeiger verwendet, ist es nicht garantiert, dass er abstürzt. Der Zeiger p wird beim Löschen nicht auf Null gesetzt, so dass er immer noch auf die gleiche Adresse im Speicher zeigt. Abhängig von der Implementierung von new / delete und dem Heap-Manager wird dieser Speicher möglicherweise nicht einmal wieder verwendet, so dass die Verwendung von p möglicherweise noch funktioniert, obwohl der Speicher freigegeben wurde.

    
Nic Strong 17.06.2009 10:31
quelle
1

1) Abhängig vom Compiler, unter Mac OS mit gcc 4.0.1:

%Vor%

Double free verursacht Probleme.

2) Im Allgemeinen ist das Löschen eines bereits gelöschten Zeigers nicht definiert. Sie sollten den Zeiger nach dem Löschen immer auf 0 setzen. Das Aufrufen von delete on pointer mit dem Wert 0 ist zulässig.

3) Der Grund dafür, dass die Zeichenfolge immer noch gedruckt werden kann, ist, dass der Zeiger immer noch auf den Speicher zeigt, der jetzt freigegeben wurde, aber ich würde annehmen, dass nur der Zeiger z. zurück zum freien Pool für die Wiederverwendung, der Speicher wird nicht überschrieben oder Null. Wenn Sie den Zeiger dereferenzieren, erhalten Sie immer noch die ursprünglichen Werte, es sei denn, der Speicher wird in der Zwischenzeit wiederverwendet.

    
stefanB 17.06.2009 11:28
quelle
1

delete setzt p nicht auf null, so dass es immer noch auf den Speicherort zeigt. Es hängt von der Implementierung von new / delete ab, aber normalerweise löscht nur der Teil des Speichers, der für neue Zuweisungen verfügbar ist.

Es ist wie wenn Sie eine Datei von Ihrer Festplatte löschen. Das Dateisystem markiert diesen Bereich einfach als verfügbar. Die Dateidaten sind vorhanden und können wiederhergestellt werden, solange Sie keine neuen Schreibvorgänge ausführen.

    
mempko 18.06.2009 04:48
quelle
0

Ich denke, es hängt von der Umgebung ab (Plattform / Compiler) ...
Dies führt zumindest zu unerwartetem Verhalten. Ich denke, du hast Glück, dass es in deinem Fall nicht zusammenbricht ;-)

    
fretje 17.06.2009 10:29
quelle
0

Um ein wenig zu dem hinzuzufügen, was andere gesagt haben, versuchen Sie, eine Membervariable Ihrer Klasse in der check () -Methode zu verwenden und dann zu sehen, was passiert.

Der Funktionsaufruf bei Klassen ähnelt dem normalen Funktionsaufruf, abgesehen von einem kleinen Unterschied. Die Argumente werden in beiden Fällen auf Stapel geschoben, aber im Fall eines Funktionsaufrufs eines Objekts wird "this" als erstes Argument auf den Stapel geschoben. Dieses "This" wird innerhalb der Funktion verwendet, um auf die Membervariablen zuzugreifen. Da Sie auf keine Mitgliedsvariablen zugreifen, funktioniert es. Und ja, es kann auch funktionieren, wenn Sie auf Member-Variablen zugreifen, aber Sie werden unerwartetes Verhalten bekommen, weil der Compiler den Speicher frei verwenden kann, der 'p' zugewiesen wurde. Sobald der Compiler diesen Speicher nutzt, werden Sie Abstürze bekommen. Wenn Sie beispielsweise nach dem Löschen weitere Variablen deklarieren, bevor Sie "p" erneut verwenden, stürzt es möglicherweise ab.

Edit: Wenn Ihre Methode nicht auf eine Elementvariable zugreift, ist es definitiv ein definitiver Kandidat für eine statische Methode.

    
Aamir 17.06.2009 10:32
quelle

Tags und Links