Kontext: Ich versuche, meinen Kopf um Zeiger zu wickeln. Wir haben sie erst vor ein paar Wochen in der Schule gesehen und als ich heute übte, bin ich auf einen Dummkopf gestoßen. Problem, es kann für Sie sehr einfach sein, aber ich habe wenig bis gar keine Programmiererfahrung.
Ich habe in SO einige Fragen zum Löschen von Zeigern gesehen, aber alle scheinen mit dem Löschen einer Klasse und nicht mit einem 'einfachen' Zeiger (oder was auch immer der richtige Begriff sein mag) zusammenhängen. Hier ist der Code, den ich versuche Lauf:
#include <iostream>;
using namespace std;
int main() {
int myVar,
*myPointer;
myVar = 8;
myPointer = &myVar;
cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;
// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6
// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.
// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.
}
Meine Fragen sind also:
- Warum funktioniert der erste Fall nicht? Scheint die einfachste Verwendung zu sein, um einen Zeiger zu verwenden und zu löschen? Der Fehler besagt, dass der Speicher nicht zugewiesen wurde, aber 'cout' eine Adresse zurückgegeben hat.
- Auf dem zweiten Beispiel wird der Fehler nicht ausgelöst wird , sondern ein cout des Wertes MyPointer tut noch eine Speicheradresse zurückgegeben.
- Funktioniert # 3 wirklich? Scheint mir zu funktionieren, der Zeiger speichert keine Adresse mehr. Ist dies der richtige Weg, um einen Zeiger zu löschen?
Entschuldigung für die lange Frage, wollte dies so klar wie möglich machen, auch um es noch einmal zu wiederholen, ich habe wenig Programmiererfahrung, also wenn jemand dies mit Laienbegriffen beantworten könnte, wäre es sehr dankbar!
quelle
delete
was dunew
. Es ist auch nicht erforderlich, dass sich der Zeiger nach dem Löschen auf NULL setzt. Wenn Sie dort Sicherheit wünschen, verwenden Sie intelligente Zeiger, die den Speicher für Sie freigeben und Fehler verursachen, wenn Sie versuchen, auf sie zuzugreifen, wenn sie nichts enthalten.reset
und es befreit das Alte. Um es ersatzlos freizugeben, rufen Sie anrelease
. Wenn es den Gültigkeitsbereich verlässt, wird es zerstört und kann den Speicher basierend auf dem Typ freigeben.std::unique_ptr
ist nur für einen Besitzer gedacht.std::shared_ptr
gibt es frei, wenn der letzte Besitzer die Ressource nicht mehr besitzt. Sie sind auch ausnahmesicher. Wenn Sie einer Ressource eine zuweisen und dann auf eine Ausnahme stoßen, wird die Ressource ordnungsgemäß freigegeben.Antworten:
1 & 2
Die erste Variable wurde auf dem Stapel zugewiesen. Sie können delete nur für den Speicher aufrufen, den Sie mithilfe des
new
Operators dynamisch zugewiesen haben (auf dem Heap) .3.
Das Obige hat überhaupt nichts getan . Sie haben nichts befreit, da der Zeiger auf NULL zeigte.
Folgendes sollte nicht getan werden:
Sie haben es auf NULL gerichtet und dabei den durchgesickerten Speicher (den von Ihnen zugewiesenen neuen int) zurückgelassen. Sie sollten den Speicher freigeben, auf den Sie gezeigt haben. Es gibt keine Möglichkeit
new int
mehr, auf das zugewiesene zuzugreifen , daher Speicherverlust.Der richtige Weg:
Der bessere Weg:
Wenn Sie C ++ verwenden, verwenden Sie keine Rohzeiger. Verwenden Sie stattdessen intelligente Zeiger, die diese Dinge mit geringem Aufwand für Sie erledigen können. C ++ 11 enthält mehrere .
quelle
delete myPointer
Freigabe*myPointer
. Das ist richtig. Zeigt abermyPointer
weiterhin auf einen Speicherort, der freigegeben wurde und nicht verwendet werden sollte, da es sich um UB handelt. Nach dem Ende des Gültigkeitsbereichs kann nur dann nicht mehr darauf zugegriffen werden, wenn es sich überhaupt um eine lokale Variable handelt.new
jeden Tag etwas . (Ich bin kitschig!)NULL
verhindert , dass wir es später missbrauchen.Ich glaube, Sie verstehen nicht ganz, wie Zeiger funktionieren.
Wenn Sie einen Zeiger haben, der auf einen Speicher zeigt, müssen Sie drei verschiedene Dinge verstehen:
- Der Zeiger (der Speicher) zeigt auf "was zeigt"
- diese Speicheradresse
- nicht alle Zeiger müssen ihren Speicher löschen: nur Sie müssen Speicher löschen, der dynamisch zugewiesen wurde (verwendeter
new
Operator).Vorstellen:
Als du es getan hast
In C ++ können Sie versuchen, auf
delete
einen Zeiger zu verweisen, auf den verweist, dernull
jedoch nichts bewirkt und nur keinen Fehler ausgibt.quelle
Zeiger ähneln normalen Variablen, da Sie sie nicht löschen müssen. Sie werden am Ende einer Funktionsausführung und / oder am Ende des Programms aus dem Speicher entfernt.
Sie können jedoch Zeiger verwenden, um einen 'Speicherblock' zuzuweisen, zum Beispiel wie folgt:
Dadurch wird Speicherplatz für 20000 Ganzzahlen zugewiesen. Nützlich, da der Stapel eine begrenzte Größe hat und Sie möglicherweise mit einer großen Menge von "Ints" ohne einen Stapelüberlauffehler herumspielen möchten.
Wenn Sie new aufrufen, sollten Sie am Ende Ihres Programms "löschen", da sonst ein Speicherverlust auftritt und der zugewiesene Speicherplatz niemals für andere Programme zurückgegeben wird. Um dies zu tun:
Hoffentlich hilft das.
quelle
neu wird nie genannt. Die Adresse, die cout druckt, ist also die Adresse des Speicherorts von myVar oder in diesem Fall der Wert, der myPointer zugewiesen wurde. Durch Schreiben:
du sagst:
Es gibt eine Adresse zurück, die auf einen gelöschten Speicherort verweist. Weil Sie zuerst den Zeiger erstellen und myPointer seinen Wert zuweisen, zweitens ihn löschen und drittens drucken. Wenn Sie myPointer keinen anderen Wert zuweisen, bleibt die gelöschte Adresse erhalten.
NULL ist gleich 0, Sie löschen 0, also löschen Sie nichts. Und es ist logisch, dass 0 ausgegeben wird, weil Sie Folgendes getan haben:
was gleich ist:
quelle
quelle
quelle