
Code-Muncher
Ich weiß, das ist eine ziemlich häufige Frage, aber immer noch neu für mich!
Ich verstehe das Konzept des baumelnden Zeigers nicht, habe herumgegoogelt und Testmethoden geschrieben, um einen zu finden.
Ich frage mich nur, ist das ein baumelnder Zeiger? Da jedes Beispiel, das ich gefunden habe, etwas zurückgegeben hat, versuche ich hier etwas Ähnliches!
Danke!
void foo(const std::string name)
{
// will it be Dangling pointer?!, with comments/Answer
// it could be if in new_foo, I store name into Global.
// Why?! And what is safe then?
new_foo(name.c_str());
}
void new_foo(const char* name)
{
// print name or do something with name...
}

Jack
Ein freier Zeiger ist ein Zeiger, der auf ungültige oder nicht mehr gültige Daten zeigt, zum Beispiel:
Class *object = new Class();
Class *object2 = object;
delete object;
object = nullptr;
// now object2 points to something which is not valid anymore
Dies kann sogar in Stack-zugewiesenen Objekten auftreten:
Object *method() {
Object object;
return &object;
}
Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function
Der von zurückgegebene Zeiger c_str
kann ungültig werden, wenn der String nachträglich modifiziert oder zerstört wird. In Ihrem Beispiel scheinen Sie es nicht zu ändern, aber da ist nicht klar, was Sie damit machen werden const char *name
Es ist unmöglich zu wissen, ob Ihr Code von Natur aus sicher ist oder nicht.
Wenn Sie beispielsweise den Zeiger irgendwo speichern und dann die entsprechende Zeichenfolge zerstört wird, wird der Zeiger ungültig. Wenn du benutzt const char *name
nur im Rahmen von new_foo
(z. B. für Druckzwecke), dann bleibt der Zeiger gültig.
Ein Dangling-Zeiger ist ein (Nicht-NULL-)Zeiger, der auf einen nicht zugeordneten (bereits freigegebenen) Speicherbereich zeigt.
Das obige Beispiel sollte korrekt sein, da die Zeichenfolge nicht durch new_foo geändert wird.

Ashish Ahuja
Genommen von Hier. Auch wenn dies für C gilt, ist es dasselbe für C++.
Baumelnder Zeiger
Wenn ein Zeiger auf die Speicheradresse einer Variablen zeigt, aber diese Variable nach einiger Zeit von dieser Speicherstelle gelöscht wird, während der Zeiger noch darauf zeigt, dann wird ein solcher Zeiger als baumelnder Zeiger bezeichnet und dieses Problem wird als Problem mit hängenden Zeigern.
Anfänglich

Später

Beispiel
#include<stdio.h>
int *call();
int main() {
int *ptr;
ptr = call();
fflush(stdin);
printf("%d", *ptr);
return 0;
}
int * call() {
int x=25;
++x;
return &x;
}
Seine Ausgabe wird Müll sein, weil die Variable x
ist eine lokale Variable. Sein Umfang und seine Lebensdauer liegen innerhalb des Funktionsaufrufs, also nach der Rückgabe der Adresse von x
Variable x
wird tot und der Zeiger zeigt immer noch auf diese Stelle.
Aus Stilgründen erkläre ich einen hängenden Zeiger als “einen Zeiger, der noch existiert, obwohl das Objekt, auf das er zeigte, nicht mehr existiert”.
In Ihrem Fall der Zeiger name
existiert für einen kürzeren Zeitraum als das Objekt, auf das es zeigt. Es baumelt also nie.
Innerhalb üblicher C++-Klassen baumeln Zeiger für einen sehr kurzen Zeitraum innerhalb von Destruktoren. Das liegt daran, dass die delete
Aussage ist vor dem letzten }
des Destruktors, während der Zeiger selbst zuletzt aufhört zu existieren }
. Wenn Sie sich darüber keine Gedanken machen möchten, verwenden Sie zB unique_ptr<T>
. Die T*
Zeiger baumelt für eine sehr kurze Zeit in der unique_ptr::~unique_ptr
Destruktor, der vollkommen sicher ist.
Dangling-Zeiger ist eine Situation, in der Sie gültige Zeiger im Stapel haben, aber auf ungültigen Speicher zeigen. Sie könnten in diese Situation geraten, wenn Sie den Heap-Speicher freigeben, bevor die Zeiger im Stack freigegeben werden.

Dies ist ein Sicherheitsproblem. Denn wenn Sie einen Speicher freigeben, teilen wir dem Betriebssystem mit, dass wir diesen Speicherabschnitt nicht mehr benötigen. Das Betriebssystem markiert also diesen Teil des Speichers als bereit zur Zuweisung und Zuweisung an andere Anwendungen, wenn diese Speicher anfordern.
Normalerweise wird in C++ Speicher durch ein allgemeines Muster zugewiesen und freigegeben. Der Konstruktor in einer Klasse wird aufgerufen, wenn eine Klasse initialisiert wird, und dies ist der richtige Ort, um Speicher im Heap zuzuweisen. Der Destruktor wird aufgerufen, wenn die Klasseninstanz den Gültigkeitsbereich verlässt, und dies ist der richtige Ort, um Speicher vom Heap freizugeben. Angenommen, wir haben bereits eine Klasse erstellt, die Speicher im Konstruktor bzw. Destruktor zuweist und aufhebt.
int main() {
SomeClass pointer1 = SomeClass();
SomeClass pointer2 = pointer1;
}
Im obigen Beispielcode sind zwei Variablen deklariert, die aber beide den gleichen Wert enthalten. Wenn der Konstruktor aufgerufen wird, weist er einen Heap-Speicher zu. Dann deklarieren wir eine weitere Variable und weisen denselben Wert zu. Wenn Sie in C++ einen Wert eines komplexen Typs zuweisen, wird normalerweise eine flache Kopie (es sei denn, Sie haben den Kopierkonstruktor explizit implementiert) anstelle einer tiefen Kopie ausgeführt. Das bedeutet, dass nur der Zeiger in Stack kopiert wird, aber nicht der Heap-Speicher. Eigentlich ist es aus Performance-Gründen nicht empfehlenswert, Heap-Speicher zu kopieren. Jetzt sieht das endgültige Speicherlayout so aus, dass wir zwei Zeiger haben, die auf denselben Heap-Speicher zeigen.

Wenn die Funktion nun mit der Ausführung fertig ist, verlassen lokale Variablen den Gültigkeitsbereich und rufen den Destruktor auf. Zunächst ruft pointer2 den Destruktor auf, der den Heap-Speicher freigibt. An diesem Punkt wird Zeiger1 zu einem baumelnden Zeiger. Es zeigt auf einen Speicher, der bereits freigegeben ist.

Aus diesem Beispiel haben wir verstanden, dass die Hauptursache für hängende Zeiger darin besteht, dass mehrere Besitzer für dieselbe Ressource vorhanden sind. Denn wenn ein Zeiger Speicher freigibt, wurden andere Zeiger zu baumelnden Zeigern.

Sadia Younas
//Declaring two pointer variables to int
int * ptr1;
int * ptr2;
// Allocating dynamic memory in the heap
ptr1 = new int;
ptr2 = ptr1; // Having both pointers to point same dynamic memory location
//deleting the dynamic memory location
delete ptr1;
ptr1 = nullptr;
//ptr2 is still pointing the already deleted memory location
//We call ptr2 is a dangling pointer

J. Chomel
Dangling-Pointer- und Dangling-Pointer-Problem Wenn ein Zeiger auf die Speicheradresse einer beliebigen Variablen zeigt, aber nachdem eine Variable aus diesem Speicherort gelöscht wurde, während der Zeiger immer noch auf diesen Speicherort zeigt.
Dieser Zeiger wird als baumelnder Zeiger bezeichnet, und das Problem, das zu diesem Zeitpunkt auftritt, wird als baumelndes Zeigerproblem bezeichnet.
Hier sind einige Beispiele: Problem mit baumelndem Zeiger und baumelndem Zeiger
9982900cookie-checkWas ist ein hängender Zeiger?yes
“Wird es ein baumelnder Zeiger sein?!, mit Kommentaren/Antwort ist es” — Nein ist es nicht. In Ihrem ersten Beispiel gibt es keinen hängenden Zeiger. Was Sie dort tun, ist perfekt, 100 % sicher und korrekt.
– Benjamin Lindley
1. August 2013 um 15:00 Uhr
Ich verstehe nicht, wie Sie eine haben können baumelnder Zeiger … ohne das Zeiger.
– gifnoc-gkp
1. August 2013 um 15:01 Uhr
@TheOtherGuy Ich meine, kein const char * … mit demselben const std::string
– Codefresser
1. August 2013 um 15:03 Uhr
@BenjaminLindley Nun, aus Jacks Antwort scheint es wahr zu sein, da c_str() einen Zeiger auf eine Zeichenfolge zurückgibt, die in new_foo möglicherweise nicht gültig ist …. könnte falsch sein !!
– Codefresser
1. August 2013 um 15:05 Uhr
Hinweis: Ich habe den Rückgabetyp von bearbeitet
foo
damit Sie nicht dumm dastehen, wenn Sie sagen, dass das, was Sie tun, zu 100 % sicher und korrekt ist.– Benjamin Lindley
1. August 2013 um 15:37 Uhr