Frage von WarumGeld, 31

Wie gibt man den Speicher nach folgender Deklaration eines dynamischen Arrays wieder frei (C++) ?

// Deklaration des Dynamischen 2-D Arrays
Spielfeld = new int *[hoehe];
for (int i=0; i<hoehe; i++)
{
    Spielfeld[i] = new int[breite];
}
Expertenantwort
von TeeTier, Community-Experte für programmieren, 5

Die Antwort von "ralphdieter" ist vermutlich genau das, was du wissen willst, aber um Speicherlecks zu vermeiden, nimm lieber Vektoren oder packe deinen allozierten Speicher wenigstens in einen Container für Pointer (shared_ptr oder unique_ptr)! :)

Beispiel:

#include <vector>

vector<vector<int>> spielfeld(hoehe);
for (auto &reihe : spielfeld) {
reihe.resize(breite);
}

Danach sind erstens alle Felder ordentlich mit 0 initialisiert, und du kannst über spielfeld[y][x] ganz normal und völlig ohne Laufzeit-Overhead auf einzelne "Felder" zugreifen.

Um ein Aufräumen des Speichers musst du dich nicht mehr kümmern, denn das geschieht automatisch. :)

Antwort
von ralphdieter, 6

So räumst Du auf:

for (int i=0; i<hoehe; i++)
delete[] Spielfeld[i];


delete[] Spielfeld;

Spielfeld = 0; // zur Sicherheit


Kommentar von TeeTier ,

Mit der letzten Zeile bin ich nicht einverstanden, aber das ist ein komplexes Thema auf das immer ellenlange Diskussionen folgen. Ich glaube, hier scheiden sich die Geister. :)

Ansonsten eine gute Antwort! :)

Kommentar von ralphdieter ,

Ups, das "=0" war C. Da finde ich es nach free() persönlich sehr hilfreich — im Gegensatz zu ellenlangen Diskussionen :)

Ich nehme nun an, dass der C++-Operator delete() den Zeiger selbst besser "anpinkeln" kann. Falls Du jedoch auf etwas ganz anderes hinaus wolltest, bin ich für Google-Stichworte offen (rein präventiv).

Kommentar von TeeTier ,

Gehen auch Links zu Stackoverflow? :)

http://stackoverflow.com/questions/1025589/setting-variable-to-null-after-free

http://stackoverflow.com/questions/1879550/should-one-really-set-pointers-to-nul...

Wenn du eine halbe Stunde Zeit hast, lies dir mal ruhig die ganzen Antworten mit durch, um einen Überblick zu bekommen.

Wie du sehen wirst, sind die Leute dabei durchaus geteilter Meinung. Dabei ist erst mal egal, ob es sich um C-Style free() mit NULL oder um C++-Style delete mit nullptr handelt.

Ich persönlich benutze oft Software zum Aufspüren von Speicherlecks und wenn man Zeiger nach dem free() / delete auf Null setzt, macht man sich die Fehlersuche unnötig schwer. Die Tools liefern dann nämlich falsche Fehler!

Ich denke, es kommt immer darauf an, wie man entwickelt: Wer Tools wie Valgrind nicht benutzt, erkennt subtilere Fehler vermutlich schneller, wenn er die Zeiger nach dem freigeben auf Null setzt, aber wenn man während der Entwicklung sowieso die ganzen Tests unter einer Speicheranalysesoftware laufen lässt, dann findet man Bugs wesentlich einfacher und schneller, wenn man auf ptr = NULL verzichtet.

Von daher setze ich meine Zeiger nicht auf Null, kann aber auch mit gutem Gewissen behaupten, dass ich keine Memory-Leaks, Off-By-One-Fehler oder Use-After-Free-Bugs einbaue.

Aber wie gesagt ... das ist alles erstens Ansichtssache, und zweitens ist es in vielen Firmen vorgegeben ... da kann man dann sowieso nichts machen. :)

PS: Seit C++11 benutzt man "nullptr" anstelle von "0" oder gar "NULL"! :)

Kommentar von ralphdieter ,

Danke für die Links! Ich bin aber nur drübergeflogen; um da tiefer einzusteigen bin ich nicht religiös genug :)

Nachtrag (zu meiner Ehrenrettung): Ich bin wohl von folgendem Szenario ausgegangen:

class Game {
 int *Spielfeld[];
 void start(int h, int b) {/*Frage-Code*/}
 void stop() {/*mein Code*/}
 bool active() const { return Spielfeld; }
}

Aber schon klar, auch dieses Design hat noch Luft nach oben...

Antwort
von Smexah, 20

Bei java macht das der GC, sobald keine Referenz mehr auf den Speicher zeigt. 

und:

// Deklaration des Dynamischen 2-D Arrays
Spielfeld s = new Spielfeld( hoehe);
for (int i=0; i<hoehe; i++)
{
s[i] = new int[breite];
}

So würde es auch eher compilieren :)

Keine passende Antwort gefunden?

Fragen Sie die Community