Ist es sicher, einen NULL-Zeiger zu löschen?

Lesezeit: 7 Minuten

Ist es sicher einen NULL Zeiger zu loschen
qiuxiafei

Ist es sicher, einen NULL-Zeiger zu löschen?

Und ist es ein guter Programmierstil?

  • Eine bewährte Vorgehensweise besteht darin, C++-Programme ohne einen einzigen Aufruf von zu schreiben delete. Verwenden Sie stattdessen RAII. Das heißt, verwenden std::vector<T> v(100); anstatt T* p = new T[100];verwenden Sie intelligente Zeiger wie unique_ptr<T> und shared_ptr<T> die sich um das Löschen statt um rohe Zeiger usw. kümmern.

    – fredoverflow

    19. November 2010 um 17:26 Uhr

  • Dank an make_shared (c++11) und make_unique (c++14) sollte Ihr Programm enthalten Null von new und delete

    – sp2danny

    21. Oktober 2014 um 11:54 Uhr


  • Es kann immer noch einige seltene Fälle geben, die new/delete erfordern, zB atomic: atomic> ist nicht erlaubt und atomic> hat Overhead, der in manchen Fällen nicht akzeptabel sein kann.

    – atb

    2. April 2015 um 14:05 Uhr

  • Um eine Klasse mit Ressourcenverwaltung mit RAII zu deklarieren, müssen Sie new und delete aufrufen, oder Sie sagen, es gibt eine Vorlagenklasse, um dies sogar zu verbergen.

    – VinGarcia

    21. Oktober 2016 um 1:44 Uhr

  • @VinGarcia Der Punkt ist das meiste Benutzer/Kunde (das heißt: Nicht-Bibliotheks-) Code sollte niemals geschrieben werden müssen new oder delete. Klassen, die zum Verwalten von Ressourcen entwickelt wurden, wo Standardkomponenten die Aufgabe nicht erfüllen können, können natürlich das tun, was sie tun müssen, aber der Punkt ist das Sie machen die hässlichen Sachen mit dem Speicher, den sie verwalten, nicht mit dem Endbenutzercode. Erstellen Sie also Ihre eigene Bibliothek/Hilfsklasse new/deleteund verwenden Sie stattdessen diese Klasse.

    – Unterstrich_d

    28. Oktober 2018 um 13:20 Uhr


Ist es sicher einen NULL Zeiger zu loschen
ruslik

delete führt die Überprüfung trotzdem durch, sodass die Überprüfung auf Ihrer Seite zusätzlichen Aufwand verursacht und hässlicher aussieht. EIN sehr Eine gute Praxis ist, den Zeiger danach auf NULL zu setzen delete (hilft, doppeltes Löschen und andere ähnliche Speicherbeschädigungsprobleme zu vermeiden).

Ich fände es auch toll, wenn delete standardmäßig wurde der Parameter wie in auf NULL gesetzt

#define my_delete(x) {delete x; x = NULL;}

(Ich kenne R- und L-Werte, aber wäre es nicht schön?)

  • Beachten Sie, dass es immer noch mehrere andere Zeiger geben kann, die auf dasselbe Objekt zeigen, selbst wenn Sie einen beim Löschen auf NULL setzen.

    – etw

    16. November 2010 um 2:47 Uhr

  • In den meisten Fällen in meinem Code verlässt der Zeiger den Gültigkeitsbereich, nachdem er gelöscht wurde. Viel sicherer, als es einfach auf NULL zu setzen.

    – jalf

    16. November 2010 um 4:03 Uhr

  • EIN sehr Gottes Praxis ist nicht Setzen des Zeigers auf NULL nach dem Löschen. Einen Zeiger auf NULL zu setzen, nachdem er gelöscht wurde, maskiert Speicherzuweisungsfehler, was eine sehr schlechte Sache ist. Ein Programm, das korrekt ist, löscht einen Zeiger nicht zweimal, und ein Programm, das einen Zeiger zweimal löscht sollte Absturz.

    – Dämon

    30. August 2013 um 18:48 Uhr

  • @Alice: Es ist irrelevant, was der Standard in dieser Hinsicht sagt. Der Standard definierte das Löschen eines Nullzeigers, der vor 30 Jahren aus irgendeinem absurden Grund gültig war, also ist er legal (höchstwahrscheinlich ein C-Erbe). Das zweimalige Löschen desselben Zeigers (auch nach Änderung seines Bitmusters) ist jedoch immer noch ein schwerwiegender Programmfehler. Nicht durch den Wortlaut des Standards, sondern durch Programmlogik und Eigentümerschaft. Da ist das Löschen eines Null-Zeigers, da der Null-Zeiger entspricht kein Objekt, also kann nichts gelöscht werden. Ein Programm muss exakt wissen, ob ein Objekt gültig ist und wem es gehört und wann es gelöscht werden kann.

    – Dämon

    17. März 2014 um 15:01 Uhr

  • @Damon Trotz dieser Aufhebungen Ihrer drakonischen Eigentumsregeln sind sperrfreie Strukturen nachweislich robuster als sperrbasierte. Und ja, meine Kollegen lieben mich in der Tat für das verbesserte Ausführungsprofil, das diese Strukturen bieten, und die rigorose Thread-Sicherheit, die sie aufrechterhalten, was es einfacher macht, über Code nachzudenken (großartig für die Wartung). Jedoch haben weder dies noch Ihr impliziter persönlicher Angriff etwas mit einer Definition von Korrektheit, Gültigkeit oder Eigentum zu tun. Was Sie vorschlagen, ist eine gute Faustregel, aber es ist kein universelles Gesetz und auch nicht in der Norm verankert.

    – Alice

    18. März 2014 um 15:36 Uhr

1647077411 144 Ist es sicher einen NULL Zeiger zu loschen
Chubsdad

Aus dem Entwurf des C++0x-Standards.

$5.3.5/2 – “[…]Bei beiden Alternativen kann der Wert des Operanden von delete ein Nullzeigerwert sein.[…'”

Of course, no one would ever do ‘delete’ of a pointer with NULL value, but it is safe to do. Ideally one should not have code that does deletion of a NULL pointer. But it is sometimes useful when deletion of pointers (e.g. in a container) happens in a loop. Since delete of a NULL pointer value is safe, one can really write the deletion logic without explicit checks for NULL operand to delete.

As an aside, C Standard $7.20.3.2 also says that ‘free’ on a NULL pointer does no action.

The free function causes the space
pointed to by ptr to be deallocated,
that is, made available for further
allocation. If ptr is a null pointer,
no action occurs.

  • I would really like this answer for its citations if it didn’t intentionally introduce inefficiency in non-optimized code. As the accepted answer states, deletion of a null pointer is a no-op. Therefore, checking if a pointer is null before deleting it is completely extraneous.

    – codetaku

    Mar 24, 2016 at 16:11

1647077412 289 Ist es sicher einen NULL Zeiger zu loschen
Jonathan Leffler

Yes it is safe.

There’s no harm in deleting a null pointer; it often reduces the number of tests at the tail of a function if the unallocated pointers are initialized to zero and then simply deleted.


Since the previous sentence has caused confusion, an example — which isn’t exception safe — of what is being described:

void somefunc(void)
{
    SomeType *pst = 0;
    AnotherType *pat = 0;

    …
    pst = new SomeType;
    …
    if (…)
    {
        pat = new AnotherType[10];  … } if (…) { …code manchmal mit pat… } delete[] klopfen;  pst löschen;  }

Es gibt alle möglichen Nissen, die mit dem Beispielcode ausgewählt werden können, aber das Konzept ist (hoffentlich) klar. Die Zeigervariablen werden auf Null initialisiert, so dass die delete Operationen am Ende der Funktion müssen nicht testen, ob sie im Quellcode nicht null sind; der Bibliothekscode führt diese Prüfung trotzdem durch.

  • Ich musste das ein paar Mal lesen, um es zu verstehen. Sie müssen meinen, sie am Anfang der Methode auf Null zu initialisieren, oder währenddessen, nicht am Ende, sicher? Andernfalls würden Sie einfach sowohl das Nullsetzen als auch das Löschen entfernen.

    – Benutzer207421

    8. September 2014 um 22:58 Uhr


  • @EJP: Eine nicht ganz unplausible Gliederung einer Funktion könnte sein: void func(void) { X *x1 = 0; Y *y1 = 0; … x1 = new[10] X; … y1 = new[10] Y; … delete[] y1; delete[] x1; }. Ich habe keine Blockstruktur oder Sprünge gezeigt, aber die delete[] Operationen am Ende sind wegen der Initialisierungen am Anfang sicher. Wenn etwas bis zum Ende nach sprang x1 zugewiesen wurde und davor y1 wurde zugewiesen und es gab keine Initialisierung von y1dann würde es ein undefiniertes Verhalten geben – und während der Code auf Nullheit testen könnte (von x1 und y1) vor den Löschungen ist dies nicht erforderlich.

    – Jonathan Leffler

    8. September 2014 um 23:26 Uhr

  • Es ist schön zu wissen, dass es sicher ist. Aber man könnte trotzdem eine “if (mypointer)”-Klausel verwenden, weil sie jemandem, der den Code liest, signalisiert, dass der fragliche Zeiger möglicherweise nicht gesetzt wurde, und es signalisiert, dass dies kein Fehler oder eine Peinlichkeit ist, sondern ein Teil davon das Design (ich gebe zu, ein Kommentar könnte auch verwendet werden).

    – Andreas Steane

    22. Februar 2021 um 15:09 Uhr

Das Löschen eines Nullzeigers hat keine Auswirkung. Es ist nicht unbedingt ein guter Programmierstil, weil es nicht benötigt wird, aber es ist auch nicht schlecht.

Wenn Sie nach guten Codierungspraktiken suchen, sollten Sie stattdessen intelligente Zeiger verwenden, damit Sie dies nicht tun müssen delete überhaupt.

1647077412 115 Ist es sicher einen NULL Zeiger zu loschen
Ashrasmun

Um die Antwort von ruslik zu ergänzen, können Sie in C ++ 14 diese Konstruktion verwenden:

delete std::exchange(heapObject, nullptr);

Es ist sicher, es sei denn, Sie haben den Löschoperator überladen. Wenn Sie den Löschoperator überladen haben und die Nullbedingung nicht verarbeiten, ist dies überhaupt nicht sicher.

Ist es sicher einen NULL Zeiger zu loschen
Sitesh

Da ist ein FAQ zu diesem Thema, das diese Frage beantwortet.

Die C++-Sprache garantiert, dass delete p nichts bewirkt, wenn p null ist. Da Sie den Test möglicherweise rückwärts erhalten und die meisten Testmethoden Sie dazu zwingen, jeden Verzweigungspunkt explizit zu testen, sollten Sie den redundanten if-Test nicht verwenden.

993270cookie-checkIst es sicher, einen NULL-Zeiger zu löschen?

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

Privacy policy