2009-08-13 12 views
3

Ich wundere mich über den Operator löschen [] in C++. (Ich verwende Visual Studio 2005).löschen [] und Speicherlecks

Ich habe eine nicht verwaltete DLL, die von einer verwalteten DLL aufgerufen wird. Wenn ich dieses Programm schließe, nachdem ich beim Debuggen ein paar Aufgaben ausgeführt habe, bekomme ich viele (tausende?) Speicherlecks, meistens 24 Bytes - 44 Bytes. Ich vermute, dass es an einer bestimmten nicht verwalteten DLL liegt, die ich habe.

Wie auch immer, von dem, was ich verstehe, wenn ich den folgenden Code haben:

char* pointer = new char[500] 
/* some operations... */ 
delete[] pointer; 

Dann gilt für sie alle der Speicher richtig befreit wird, bin ich richtig?

Was passiert, wenn ich den folgenden Code haben:

char* pointer = new char[500]; 
char* pointerIt = pointer; 
/* some code perhaps to iterate over the whole memory block, like so */ 
for (int i = 0; i < 250; i++){ // only iterate halfway 
    *pointerIt = 0; 
    pointerIt++; 
} 

delete[] pointer; 

Der Speicher nach rechts durch den Zeiger gezeigt wird gelöscht? Das bedeutet, dass pointerIt jetzt nicht auf gültigen Speicher zeigt. Aber das ist in Ordnung, weil ich beide Zeiger auf NULL setzen kann, oder?

Wie auch immer, was passiert jetzt, wenn ich dies tun:

char* pointerFirstPosition = new char[500]; 
char* pointerIt = pointerFirstPosition; 

for (int i = 0; i < 250; i++){ // only iterate halfway 
    *pointerIt = 0; 
    pointerIt++; 
} 

delete[] pointerIt; // delete the pointer iterator... 

Wird von pointerIt bis zu pointerIt +500 den Speicherblock wies auf diesen Code löschen? Oder wird der Speicherblock gelöscht, auf den pointerFirstPos auf pointerFirstPos +500 zeigt?

Könnte dies zu einem Speicherleck führen?

Entschuldigung für die langatmige Nachricht, ich versuche, meine Botschaft klar zu vermitteln.

Danke,

kreb

+1

„Aber das ist okay, weil ich beiden Zeiger auf NULL gesetzt, nicht wahr?“ Nun, Sie sollten mit den Zeigern fertig sein ... – GManNickG

Antwort

4

Erste Frage Satz:

char* pointer = new char[500] 
/* some operations... */ 
delete[] pointer; 

Dann wird der gesamte Speicher für sie korrekt freigegeben wird, habe ich recht?

richtig.

Zweite Frage Satz:

char* pointer = new char[500]; 
char* pointerIt = pointer; 
/* some code perhaps to iterate over the whole memory block, like so */ 
for (int i = 0; i < 250; i++){ // only iterate halfway 
    *pointerIt = 0; 
    pointerIt++; 
} 

delete[] pointer; 

Der Speicher zu spitz durch Zeiger rechts gelöscht? Es bedeutet also, dass pointerIt jetzt nicht auf gültige Speicher zeigt .. Aber das ist in Ordnung, weil ich beide Zeiger auf Null setzen kann, oder?

Der Speicher pointer hält eine Adresse vollständig ja delted zu ist. Sowohl pointer als auch pointerIt enthalten eine Adresse für ungültigen Speicher. Jeder Zeiger ist einfach eine Variable und jede Variable ist unabhängig. So speichern beide ihre eigene Adresse unabhängig voneinander. Der Dereferenzoperator * gibt Ihnen einfach die Variable an dieser Adresse. Die Variable an dieser Adresse ist eine andere Variable als die Zeigervariable.

Dritte Frage Satz:

Sie sollten nur die Adresse werden zu löschen, die zugewiesen wurde, das gesamte Array. Sie haben undefinierte Ergebnisse, wenn Sie versuchen, ein partielles Array zu löschen. Könnte es zu einem Speicherleck kommen? Könnte es möglicherweise zu einem Absturz führen? Möglicherweise könnte es dazu führen, dass ....? Möglicherweise.

Also löschen Sie nur, was Sie zuweisen. Wenn Sie ein Array zuweisen, löschen Sie mit delete[]10, wenn Sie einen Typ löschen, der kein Array ist, das Sie mit delete löschen. Hier

ist ein eample von etwas, das in Ordnung ist nur für Klarheit:

char* pointer = new char[500]; 
char* pointerIt = pointer; 
//This is fine because you are deleting the same address: 
delete[] pointerIt; 
//The memory that both variables point to is freed, do not try to free again 
+2

Es ist undefiniert, 'delete' oder' delete [] 'etwas anderes als das, was mit' new' oder 'new []' erstellt wurde. – GManNickG

+0

Danke, das habe ich vermutet. Aber sagen wir, zum Beispiel im dritten Fragensatz, setze ich pointerIt = pointerFirstPosition, dann lösche [] pointerIt, ist das noch undefiniert? Ich arbeite mit dem OLD-Code von jemand anderem, er hat das Unternehmen bereits verlassen, und ich versuche herauszufinden, ob das der Grund für die Speicherlecks ist. – krebstar

+0

Nur für Tritte habe ich das unter g ++ 4.4.1 getestet - im Grunde genommen derselbe Code wie das, was Sie in Ihrem dritten Codebeispiel haben, außer dass 'pointerIt' auf halber Höhe des Arrays verschoben wurde. Der Aufruf von 'delete []' auf 'pointerIt' macht' pointer' ungültig, aber offensichtlich kann dieses Verhalten nicht von jedem Compiler erwartet werden, wenn das Verhalten nicht definiert ist. –

0

Check-out boost :: shared_ptr oder boost :: scoped_ptr und nie Sorgen um diese wieder. Dies gibt Ihnen eine statische & Referenz gezählt, um Ihren Speicher zu verwalten.

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm

+1

Wenn ich das mache, muss ich so viele Projekte ändern .. :(Etwas, das mein Manager nicht rechtfertigen kann. – krebstar

+0

Für zukünftigen Code, dann. Verwenden Sie 'std :: vector' und kin. Keine manuelle Speicherzuweisungen * * immer ** – GManNickG

+0

Ok, danke Jungs, sehr hilfreich :) – krebstar