Aufrufen von delete für eine auf dem Stack zugewiesene Variable

Lesezeit: 5 Minuten

Aufrufen von delete fur eine auf dem Stack zugewiesene Variable
Unistudent

Ist es, abgesehen von Programmierstil und Design, “sicher”, delete für eine auf dem Stack zugewiesene Variable aufzurufen?

Zum Beispiel:

   int nAmount;
   delete &nAmount;

oder

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}

  • Siehe auch: stackoverflow.com/questions/434140/…

    – jdt141

    14. Januar 2009 um 3:57 Uhr

  • Beachten Sie, dass Ihr zweites Beispiel nicht auf dem Stapel sein muss. nAmount wäre lokal für das Speicherbeispiel, in dem es vorhanden ist.

    – Drew Dormann

    14. Januar 2009 um 4:33 Uhr

  • Ungefähr so ​​sicher, als würde man sich eine spitze Nadel ins Auge stechen.

    – paxdiablo

    14. Januar 2009 um 5:46 Uhr

  • nasale Dämonen – das ist, was passiert

    – BЈовић

    20. September 2012 um 13:17 Uhr


  • Ein Kätzchen wird irgendwo getötet.

    – Tadeusz Kopec für die Ukraine

    20. September 2012 um 13:18 Uhr

1646949609 957 Aufrufen von delete fur eine auf dem Stack zugewiesene Variable
Herr Fuoz

Neines ist nicht sicher anzurufen delete auf einer Stack-zugewiesenen Variablen. Sie sollten nur anrufen delete auf Dinge, die von erstellt wurden new.

  • Für jeden malloc oder calloces sollte genau eine geben free.
  • Für jeden new es sollte genau eine geben delete.
  • Für jeden new[] es sollte genau eine geben delete[].
  • Für jede Stapelzuweisung sollte es keine explizite Freigabe oder Löschung geben. Der Destruktor wird ggf. automatisch aufgerufen.

Im Allgemeinen können Sie keines davon mischen und anpassen, z. B. nein free-ing oder delete[]-ing ein new Objekt. Dies führt zu undefiniertem Verhalten.

  • Danke! Mein Compiler hat keinen Fehler festgestellt, aber ich war definitiv misstrauisch, ob es legitim war.

    – Unistudent

    14. Januar 2009 um 3:50 Uhr

  • “Sollte” ist ein besseres Wort. „Muss“ impliziert, dass malloc/new/new[] schlägt fehl, wenn free/delete/delete[] fehlt, was nicht der Fall ist. Die Verwendung von “genau einem” hat die Implikation, die Sie meiner Meinung nach anstreben.

    – Zooba

    14. Januar 2009 um 10:32 Uhr

Nun, versuchen wir es:

jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault

Es ist also anscheinend überhaupt nicht sicher.

  • Ich weiß, dass dies eine alte Antwort ist, aber ich fühle mich gezwungen zu kommentieren, dass das Ausprobieren von etwas möglicherweise nicht der beste Weg ist, um zu beweisen, dass es sicher ist. Wenn es funktioniert hat, bedeutet das nicht, dass die Operation sicher ist oder dass das Verhalten genau definiert ist, es würde nur beweisen, dass es funktioniert hat das eine Mal. (Sie können auf diese Weise beweisen, dass die Dinge funktionieren nicht aber die Umkehrung gilt nicht immer.)

    – CDhowie

    8. Oktober 2014 um 20:29 Uhr


  • @cdhowie Dies ist eine irrelevante Bemerkung. Etwas ausprobieren und feststellen, dass es unsicher ist tut beweisen, dass es unsicher ist. Dies ist, was die Antwort tut. Wenn der Antwortende sein Beispiel nicht für segfault gefunden hätte, hätte er es möglicherweise einfach nicht gepostet. Sie wissen nicht, wie viele Dinge er versucht hat, bevor er zu diesem Beispiel kam.

    – jwg

    11. November 2015 um 17:30 Uhr

  • @jwg Ich glaube nicht, dass du cdhowies Punkt hast. Es gibt viele Dinge in C++, die das sind nicht sicher aber kann Arbeit. Ich bin sicher, dass Sie einen Compiler finden können, der Code erzeugt, der keinen Segfault verursacht, weil er dachte, dass dies eine großartige Funktion wäre. Alles funktioniert einfach super. Jetzt wechseln Sie den Compiler und stellen fest, dass, nur weil Sie mit dem vorherigen Compiler keinen Fehler erhalten haben, dies nicht bedeutet, dass Ihr Code nicht schlecht ist und mit keinem anderen Compiler funktioniert. Informatik ist komplexer als ‘Diesmal hat es funktioniert, also muss es vollkommen in Ordnung sein.’ Ganz zu schweigen vom Konzept des „undefinierten Verhaltens“

    – RekursiveExceptionException

    20. Juli 2017 um 21:52 Uhr


  • @jwg Um fair zu sein, ich glaube, ich habe es getan.

    – RekursiveExceptionException

    24. Juli 2017 um 22:18 Uhr

Denken Sie daran, dass, wenn Sie einen Speicherblock mit new (oder malloc für diese Angelegenheit) zuweisen, der tatsächlich zugewiesene Speicherblock größer ist als das, was Sie angefordert haben. Der Speicherblock wird auch einige Buchhaltungsinformationen enthalten, so dass, wenn Sie den Block freigeben, er leicht zurück in den freien Pool gestellt und möglicherweise mit benachbarten freien Blöcken verschmolzen werden kann.

Wenn Sie versuchen, Speicher freizugeben, den Sie nicht von new erhalten haben, sind diese Buchhaltungsinformationen nicht vorhanden, aber das System verhält sich so, wie es ist, und die Ergebnisse werden unvorhersehbar (normalerweise schlecht) sein.

1646949610 193 Aufrufen von delete fur eine auf dem Stack zugewiesene Variable
Sergej Kalinitschenko

Ja, es ist ein undefiniertes Verhalten: Passing to delete alles, was nicht kam new ist UB:

C++-Standard, Abschnitt 3.7.3.2.3: Der Wert des ersten Arguments, das einer der in der Standardbibliothek bereitgestellten Freigabefunktionen zugeführt wird, kann a sein null Zeigerwert; Wenn dies der Fall ist und die Freigabefunktion in der Standardbibliothek bereitgestellt wird, hat der Aufruf der Freigabefunktion keine Wirkung. Andernfalls wird der Wert geliefert operator delete(void*) in der Standardbibliothek muss einer der Werte sein, die von einem vorherigen Aufruf von entweder zurückgegeben werden operator new(std::size_t) oder operator new(std::size_t, const std::nothrow_t&) in der Standardbibliothek.

Die Folgen von undefiniertem Verhalten sind, nun ja, undefiniert. „Nichts passiert“ ist eine ebenso gültige Konsequenz wie alles andere. Normalerweise passiert jedoch “sofort nichts”: Das Freigeben eines ungültigen Speicherblocks kann schwerwiegende Folgen bei nachfolgenden Aufrufen des Zuordners haben.

Nachdem ich ein bisschen mit g++ 4.4 in Windows gespielt hatte, bekam ich sehr interessante Ergebnisse:

  1. Der Aufruf von delete für eine Stack-Variable scheint nichts zu bewirken. Keine Fehler werfen, aber ich kann nach dem Löschen problemlos auf die Variable zugreifen.

  2. Eine Klasse mit einer Methode mit haben delete this löscht das Objekt erfolgreich, wenn es im Heap allokiert ist, aber nicht, wenn es im Stack allokiert ist (wenn es im Stack ist, passiert nichts).

  • Ihre Antwort ist tatsächlich relevant für die Frage. Es gibt immer zu viele evangelistische Programmierer auf SO, die jeden verurteilen, der aus reiner Neugier (der Grund, warum ich hier bin) eine Frage stellt, was der Standard ist, der in unerwarteten Sonderfällen einer Sprache auftreten sollte.

    – Joey Carson

    3. April 2014 um 20:19 Uhr

Niemand kann wissen, was passiert. Dies ruft undefiniertes Verhalten hervor, sodass buchstäblich alles passieren kann. Tu das nicht.

  • Ihre Antwort ist tatsächlich relevant für die Frage. Es gibt immer zu viele evangelistische Programmierer auf SO, die jeden verurteilen, der aus reiner Neugier (der Grund, warum ich hier bin) eine Frage stellt, was der Standard ist, der in unerwarteten Sonderfällen einer Sprache auftreten sollte.

    – Joey Carson

    3. April 2014 um 20:19 Uhr

Aufrufen von delete fur eine auf dem Stack zugewiesene Variable
Wein

Nein, Speicher, der mit new zugewiesen wurde, sollte mit dem delete-Operator gelöscht werden, und der mit malloc zugewiesene sollte mit free gelöscht werden. Und es ist nicht erforderlich, die Variablen, die auf dem Stapel zugewiesen sind, freizugeben.

989100cookie-checkAufrufen von delete für eine auf dem Stack zugewiesene Variable

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

Privacy policy