C ++内存泄漏检测在错误的时间发生? (C阵列)

时间:2017-01-25 19:00:20

标签: c++ memory-leaks

我在C ++中有以下结构(不要问我为什么不使用std::vector而不是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();
}

因为我的印象是_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();
}

发生,即首先调用析构函数,而不是:

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

将在之后调用析构函数。

修改: 泄漏报告:

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: <    (08@HP> 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)来填充值。

2 个答案:

答案 0 :(得分:3)

如果程序退出,你显然没有任何内存泄漏,因为所有内存都被传回操作系统。获取析构函数的最简单方法是添加另一个范围:

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

答案 1 :(得分: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
    }