2017-01-25 3 views
1

У меня есть следующая структура в C++ (не спрашивайте, почему я не использую std::vector вместо массивов C, это не вопрос).C++ обнаружение утечки памяти происходит в неправильное время? (C Массивы)

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; 
    } 
}; 

Я использую VS2015 и я использую:

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

с

_CrtDumpMemoryLeaks(); 

для обнаружения утечек памяти и с удивлением увидел, что у меня была утечка памяти со следующим кодом :

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

как я wa что _CrtDumpMemoryLeaks() будет обнаруживать и отображать утечки памяти после выполнения (и, следовательно, деструктор пиццы был бы вызван). Как выясняется, следующий код

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

не вызывает утечки памяти. Могу ли я просто недоразумение этой цитаты из MSDN:

вы можете поместить вызов _CrtDumpMemoryLeaks перед выходом приложения точки для отображения отчета памяти течи, когда приложение выходит

или что-то еще Здесь?

я ожидал:

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

иметь место, то есть деструктор первой, а не:

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

где деструктор будет вызван после.

EDIT: Leak Доклад:

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. 

Здесь я использовал (x+1)*(y+1) для заполнения значения.

+0

Вы можете показать отчет утечки? Он должен показывать номера строк, в которых распределение было выполнено для каждого блока, который просочился. –

+0

Возможный дубликат [утечки памяти, несмотря на вызов деструктора] (http://stackoverflow.com/questions/30325372/memory-leaks-despite-destructor-call) – LogicStuff

+1

Не связано с вашей проблемой, но у вас есть ошибка в 'y < w'. Он должен читать 'y NPE

ответ

3

Если программа завершена, у вас, очевидно, нет утечек памяти, так как вся память возвращается в ОС. Самый простой способ получить деструктор, называемый просто добавить другой объем:

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

Или OP может просто вызвать '_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);' в начале своего приложения. –

+0

@ AlgirdasPreidžius, я думаю, это требует отдельного ответа. – SergeyA

+0

Это действительно решает проблему –

3

Как уже упоминалось в статье, вы linked in the question:

Если приложение имеет несколько выходов, вам не нужно вручную поместите вызов _CrtDumpMemoryLeaks в каждую точку выхода. Вызов _CrtSetDbgFlag в начале вашего приложения приведет к автоматическому вызову _CrtDumpMemoryLeaks в каждой точке выхода. Вы должны установить два битовых поля, показанные здесь: _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);.

Таким образом, вы могли бы назвать его следующим образом:

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

 Смежные вопросы

  • Нет связанных вопросов^_^