2016-10-21 6 views
0

In meinem C++ Spiel habe ich ein Array von Zeigern auf EnemyType s. Früher habe ich von Visual Leak Detector Speicherlecks zu erkennen, und es sagt mir, ich habe ein Leck in dem folgenden Code:C++ Speicherverlust beim Erstellen eines Arrays

vector<EnemyType*> enemyTypes(number_of_lines); 

for (int i = 0; i < number_of_lines; i++) 
{ 
    enemyTypes[i] = new EnemyType(); 
} 

Sagen wir number_of_lines 3 in diesem Fall. Wie ist es möglich, dass ich hier ein Leck erstelle? Kann ich etwas dagegen tun?

Ich habe C++ vor ungefähr einem Monat gelernt und lerne immer noch jeden Tag, aber ich kann einige Dinge nicht verstehen (so), ohne dass mich jemand erklärt.

EDIT: Ich habe den Code geändert, um einen Vektor anstelle einer einfachen Array zu verwenden.

+1

Haben Sie Vektoren ausprobiert? –

+0

Sie erstellen nur ein Leck, wenn Sie vergessen, den Speicher freizugeben. Der obige Code zeigt dieses Problem nicht. Erstellen Sie ein MCVE: http://StackOverflow.com/Help/Mcve –

+1

Wenn 'enemyTypes' lokal für eine Methode ist und Sie nicht jedes Element (und das Array selbst) löschen, dann haben Sie ein Leck. Erwägen Sie die Verwendung eines 'std :: vector ', dynamischer Speicher ist nicht immer wünschenswert, und wenn er verwendet wird, könnten intelligente Smartpointer den Verwaltungsteil nutzen. – Jack

Antwort

1

Von Ihrem ursprünglichen Code:

EnemyType** enemyTypes{ new EnemyType*[number_of_lines] }; 

for (int i = 0; i < number_of_lines; i++) 
{ 
    enemyTypes[i] = new EnemyType(); 
} 

Wenn Sie Speicher in C++ zuteilen new verwenden, haben Sie es ausplanen delete (oder delete[] wenn Sie ein Array zugeordnet sind, wie Ihr enemyTypes).

Wir sehen nur einen Teil Ihres Codes, aber ich denke, Sie tun keine Freigabe, wenn Sie den Speicher nicht mehr benötigen.

By the way, sollten Sie vermeiden, nur das Zuweisen von Speicher, oder verteilen sie durch verwaltete Zeiger:

#include <vector> 
#include <memory> 

// ... 

std::vector<std::unique_ptr<EnemyType>> enemy_types(number_of_lines); 

for (auto& enemy_type : enemy_types) 
{ 
    enemy_type = std::make_unique<EnemyType>(); 
} 

Je nachdem, wie Sie Ihre Daten verwenden, können Sie auch vermeiden Zeiger:

std::vector<EnemyType> enemy_types(number_of_lines); 
0

Stellen Sie bei Verwendung des Operators new sicher, dass Sie jedes von Ihnen erstellte Objekt löschen.

Eine gute Alternative könnte Smart Pointer von STL oder Boost-Bibliothek verwenden. Sie löschen Ihr Objekt automatisch, wenn es unbenutzt wurde, und vermeiden so Speicherlecks.

1

Der Operator new weist Speicher dynamisch zu.

Irgendein Code muss schließlich diesen Speicher mit dem entsprechenden Operator delete freigeben. Wenn Ihr Code dies nicht tut, wird der Speicher niemals freigegeben. Das wird zu einem Leck, wenn Ihr Programm die Spur verliert (z. B. hört der Zeiger, der das Ergebnis von new enthält, nicht mehr auf).

Eine leicht modifizierte Version des Codes

int func() 
{ 
    EnemyType** enemyTypes{ new EnemyType*[number_of_lines] }; 

    for (int i = 0; i < number_of_lines; i++) 
    { 
     enemyTypes[i] = new EnemyType(); 
    } 
} 

Der Zeiger enemyTypes hört auf zu existieren, wie die Funktion zurückkehrt (da sie außerhalb des Bereichs geht). Eine Konsequenz ist, dass der Speicher, der mit der ersten Verwendung des Operators new erzeugt wurde, niemals freigegeben wird UND kein Zeiger existiert, der darauf zeigt. Da auf diesen Speicher nicht zugegriffen werden kann, kann auf die Ergebnisse des Operators 10 in der Schleife auch nicht zugegriffen werden (da die einzige Stelle, an der diese Ergebnisse gespeichert werden, in dem dynamisch zugewiesenen Array liegt, das durch enemyTypes identifiziert wird).

Der gesamte Speicher ist daher an diesem Punkt geleakt (der dynamisch zugewiesene Speicher kann von Ihrem Programm nicht wiederhergestellt werden, es sei denn, Sie verwenden eine Technik außerhalb der Grenzen von C++).Verschiedene Speicherprüfer - wenn Sie sie verwenden - melden ein Leck entsprechend ... entweder an dem Punkt, an dem die Funktion zurückkehrt, oder wenn das Programm beendet wird.

0

Es stellte sich heraus, dass ich nie den Speicher freigab (wie andere Leute mir sagten), aber Visual Leak Detector zeigte mir nur, wo dieser Speicher zugewiesen wurde und nicht wo das Leck passiert ist.

Verwandte Themen