2017-01-25 4 views
1

Ich habe die folgende Struktur in C++ (fragen Sie nicht, warum ich nicht std::vector anstelle von C-Arrays verwende, das ist nicht die Frage).C++ Speicherleckerkennung passiert zur falschen Zeit? (C-Arrays)

struct Pizza { 
    int w; 
    int h; 
    char** pizza; 
    Pizza(int width, int height) { 
     w = width; 
     h = height; 
     pizza = new char*[w]; 
     for (int x = 0; x < w; x++) { 
      pizza[x] = new char[h]; 
      for (int y = 0; y < h; y++) { 
       pizza[x][y] = '\0'; 
      } 
     } 
    } 
    ~Pizza() { 
     for (int x = 0; x < w; x++) { 
      delete[] pizza[x]; 
     } 
     delete[] pizza; 
    } 
}; 

Ich verwende VS2015 und bin mit:

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 

mit

_CrtDumpMemoryLeaks(); 

Speicherlecks zu erkennen und war überrascht zu sehen, dass ich mit dem folgenden Code ein Speicherleck hatte :

int main() { 
    Pizza p(10,10); 
    _CrtDumpMemoryLeaks(); 
} 

wie ich wa s unter dem Eindruck, dass _CrtDumpMemoryLeaks() nur Speicherlecks nach der Ausführung erkennen und anzeigen würde (und daher würde der Pizza-Destruktor aufgerufen worden sein). Es stellt sich heraus, dass der folgende Code

int main() { 
    Pizza *p = new Pizza(10,10); 
    delete p; 
    _CrtDumpMemoryLeaks(); 
} 

kein Speicherleck erzeugt. Bin ich Missverständnis gerade dieses Zitat von MSDN:

Sie einen Anruf _CrtDumpMemoryLeaks vor einer Anwendung Ausfahrt Punkt platzieren können einen Speicher-Leck-Bericht angezeigt werden, wenn die Anwendung

oder verlässt etwas anderes los hier?

Ich erwartete:

int main() { 
    Pizza p(10,10); 
    // Imaginary p.~Pizza(); 
    _CrtDumpMemoryLeaks(); 
} 

stattzufinden, das heißt die destructor erste genannt wird, statt:

int main() { 
    Pizza p(10,10); 
    _CrtDumpMemoryLeaks(); 
    // Imaginary p.~Pizza(); 
} 

wo die destructor nach aufgerufen werden würde.

EDIT: Leak Report:

Detected memory leaks! 
Dumping objects -> 
{170} normal block at 0x01364070, 10 bytes long. 
Data: < (2<FPZd> 0A 14 1E 28 32 3C 46 50 5A 64 
{169} normal block at 0x013642D8, 10 bytes long. 
Data: < $-6?HQZ> 09 12 1B 24 2D 36 3F 48 51 5A 
{168} normal block at 0x01364380, 10 bytes long. 
Data: < ([email protected]> 08 10 18 20 28 30 38 40 48 50 
{167} normal block at 0x013640E0, 10 bytes long. 
Data: < #*18?F> 07 0E 15 1C 23 2A 31 38 3F 46 
{166} normal block at 0x01364658, 10 bytes long. 
Data: <  $*06<> 06 0C 12 18 1E 24 2A 30 36 3C 
{165} normal block at 0x013644D0, 10 bytes long. 
Data: <  #(-2> 05 0A 0F 14 19 1E 23 28 2D 32 
{164} normal block at 0x01364348, 10 bytes long. 
Data: <  $(> 04 08 0C 10 14 18 1C 20 24 28 
{163} normal block at 0x013645E8, 10 bytes long. 
Data: <   > 03 06 09 0C 0F 12 15 18 1B 1E 
{162} normal block at 0x013643B8, 10 bytes long. 
Data: <   > 02 04 06 08 0A 0C 0E 10 12 14 
{161} normal block at 0x01364700, 10 bytes long. 
Data: <   > 01 02 03 04 05 06 07 08 09 0A 
{160} normal block at 0x0135DCA8, 40 bytes long. 
Data: < G6 C6 E6 HC6 > 00 47 36 01 B8 43 36 01 E8 45 36 01 48 43 36 01 
Object dump complete. 

Hier verwendete ich (x+1)*(y+1) die Werte zu füllen.

+0

Können Sie das Leck Bericht zeigen? Es sollte Zeilennummern enthalten, bei denen die Zuweisung für jeden blockierten Block aufgetreten ist. –

+0

Mögliches Duplikat von [Speicherlecks trotz Destruktoraufrufs] (http://stackoverflow.com/questions/30325372/memory-leaks-despite-destructor-call) – LogicStuff

+1

Nicht verwandt mit Ihrem Problem, aber Sie haben einen Fehler in 'y < w'. Es sollte "y NPE

Antwort

3

Wenn das Programm beendet wird, haben Sie offensichtlich keine Speicherverluste, da der gesamte Speicher an das Betriebssystem zurückgegeben wird. Der einfachste Weg, um den destructor genannt zu bekommen, ist einfach ein anderen Rahmen hinzuzufügen:

int main() { 
    { 
     Pizza p(10,10); 
    } 
    _CrtDumpMemoryLeaks(); 
} 
+1

Oder OP könnte einfach '_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);' zu Beginn seiner Anwendung aufrufen. –

+0

@ AlgirdasPreidžius, denke ich, dies garantiert eine separate Antwort. – SergeyA

+0

Dies löst tatsächlich das Problem –

3

Wie im Artikel erwähnt, Sie linked in the question:

Wenn Ihre Anwendung mehr Ausgänge haben, Sie müssen nicht manuell Rufen Sie _CrtDumpMemoryLeaks an jedem Ausgangspunkt auf. Ein Anruf zu _CrtSetDbgFlag zu Beginn Ihrer Anwendung wird einen automatischen Anruf an _CrtDumpMemoryLeaks an jedem Ausgangspunkt verursachen. Sie müssen die beiden hier gezeigten Bit-Felder einstellen: _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);.

So könnte man es nennen, wie folgt:

int main() 
    { 
    _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 
    // Your actual code 
    } 
Verwandte Themen