2017-01-25 34 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(); 
} 

as我wa因爲_CrtDumpMemoryLeaks()只會在執行後檢測並顯示內存泄漏(因此會調用Pizza析構函數)。結果如下代碼

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

不會產生內存泄漏。我只是從MSDN誤解這句話:

可以放置到_CrtDumpMemoryLeaks調用應用程序退出之前 點,當應用程序退出

或者是別的事情,以顯示內存泄漏報告在這?

我期待:

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

發生,即析構函數首先被調用,而不是:

​​

在析構函數將被稱爲後。

編輯: 泄漏報告:

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 
    }