Was ist ein hängender Zeiger?

Lesezeit: 8 Minuten

Was ist ein hangender Zeiger
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...   
}

  • “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


1647186611 441 Was ist ein hangender Zeiger
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.

  • +(1/2) für diese Antwort. Die Anfangserklärung ist gut. Der Rat am Ende ist paranoid und unnötig. Der Code des OP ist sicher.

    – Benjamin Lindley

    1. August 2013 um 14:55 Uhr


  • @BenjaminLindley … und rücksichtslos und unnötig unsicher. Herumarbeiten std::string mit strdup ist einfach lächerlich.

    – R.Martinho Fernandes

    1. August 2013 um 14:59 Uhr


  • @Jack Wie um alles in der Welt könnte new_foo Greifen Sie auf den Funktionsparameter von zu foo um es zu ändern? Das Beispiel des OP ist sicher.

    – Angew ist nicht mehr stolz auf SO

    1. August 2013 um 15:00 Uhr

  • @codemuncher: global_name wird zu einem baumelnden Zeiger, wenn foo zurück, da die Zeichenfolge, aus der der Zeiger stammt (string name in foo) wird zu diesem Zeitpunkt zerstört.

    – Benjamin Lindley

    1. August 2013 um 15:26 Uhr

  • @codemuncher Ich bin mir nicht sicher, was Sie “sicher” machen wollen. Die Regel ist einfach: Alle Zeiger müssen entweder null sein oder auf ein gültiges “Objekt” zeigen. (Ich verwende „Objekt“ im Sinne des C++-Standards.) Wenn Sie etwas löschen, müssen Sie (per Design) sicherstellen, dass keine Zeiger darauf mehr vorhanden sind. Und in Bezug auf den Rückgabewert von std::string::c_str(): der nur Zeit, in der Sie diese Funktion verwenden sollten, ist, wenn Sie eine Schnittstelle zu einer Legacy-Funktion herstellen, für die a erforderlich ist char const*.

    – James Kanze

    2. August 2013 um 8:04 Uhr

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.

  • @Miklós Homolya sein “const” .. was meinst du mit “modify in new_foo”?!

    – Codefresser

    1. August 2013 um 15:14 Uhr

  • Diese Verwendung von “const” ist eine (Compiler-) Front-End-Funktion, die durch einen const_cast überwunden werden könnte. Das Problem besteht darin, standardkonform eine Referenz auf die Stack-Variable ‘name’ zu bekommen, da der Code der Funktion ‘foo’ bereits vorgegeben ist.

    Benutzer2545918

    1. August 2013 um 15:33 Uhr

  • Ich denke nicht new_foo kann den Namen ändern

    – Deqing

    1. August 2013 um 15:35 Uhr

1647186611 139 Was ist ein hangender Zeiger
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

Geben Sie hier die Bildbeschreibung ein

Später

Geben Sie hier die Bildbeschreibung ein

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.

  • Der „hängende Zeiger“ ist eines der schädlichsten Probleme in C und einer der Gründe, warum C++ Referenzen erstellt hat. Leider können Referenzen auf die gleiche Weise baumeln. Intelligente Zeiger (en.wikipedia.org/wiki/Smart_pointer) sind eine Möglichkeit, mit dem Problem umzugehen. Leider ist das folgende Verhalten undefiniert, so dass das Ergebnis manchmal zu ‘Müll’ wird (wenn ein anderer Teil des Programms diesen Speicherbereich verwendet), und manchmal nicht. Dies führt zu der Art von schwer zu replizierendem Fehler, der die Leute dazu bringt, sich die Haare zu raufen.

    – Dana

    17. Mai 2018 um 23:18 Uhr


  • @Yatin, du hast ein Zitat bearbeitet, obwohl es nicht im Zitatformat ist, hat es den Link, von dem es stammt, sei bitte vorsichtig damit.

    – Anastaciu

    10. August 2020 um 10:18 Uhr

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.

1647186613 724 Was ist ein hangender Zeiger

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.

1647186614 399 Was ist ein hangender Zeiger

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.

1647186615 798 Was ist ein hangender Zeiger

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.

1647186615 413 Was ist ein hangender Zeiger
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

1647186616 695 Was ist ein hangender Zeiger
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

998290cookie-checkWas ist ein hängender Zeiger?

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

Privacy policy