C++ Visual Studio - 在简单示例中解释内存泄漏检测

C++ Visual Studio - Interpreting memory leak detection on simple example

我想开始使用 C++ 中的 VS 内存泄漏检测。由于我更习惯 Java,这里是我遇到问题的简单示例。我想测试简单的 class 泄漏。 Header:

#pragma once
class Tested{
public:
    Tested();
    ~Tested();

    const int N = 10;
    const int PARS = 3;

    float* getDataLine(int n);

private:
    float** data;
};

Cpp 文件:

#include "stdafx.h"
#include "Tested.h"
using namespace std;

Tested::Tested() {
    data = new float*[N];
    for (int i = 0; i < N; i++){
        data[i] = new float[PARS];
    }
}

float* Tested::getDataLine(int n){
    return data[n];
}

Tested::~Tested() {
    for (int i = 0; i < N; i++){
        delete[] data[i];
    }
    delete[] data;
}

stdafx.h

#pragma once
#include "targetver.h"
#include "CppUnitTest.h"

// http://msdn.microsoft.com/en-us/library/e5ewb1h3(v=vs.71).aspx
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
    #ifndef DBG_NEW
        #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
        #define new DBG_NEW
    #endif
#endif  // _DEBUG

最后是测试 class:

#include "stdafx.h"
#include "Tested.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Test{
    TEST_CLASS(MemoryLeakTest){
    public:
        TEST_METHOD(AllDataAccess){
            //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
            //_CrtSetBreakAlloc(147);
            {
                Tested t;
                float* line = t.getDataLine(0);
                line[0] = 10;
            }
            _CrtDumpMemoryLeaks();
        }
    };
}

现在,如果我 comment-out 行 'delete[] data;',泄漏检测报告很好并且指向初始化数据**的行:

Detected memory leaks!
Dumping objects ->
c:\users\j\dropbox\workspace\visualstudio\memoryleaktest\neurontest\tested.cpp(7) : {148} normal block at 0x06B09D68, 40 bytes long.
 Data: <        `       > D0 9D B0 06 18 9E B0 06 60 9E B0 06 A8 9E B0 06 
{147} normal block at 0x06B09BA8, 4 bytes long.
 Data: <    > F0 D9 16 0F 
Object dump complete.

但是如果我使用 'delete[] data;'(如图所示),检测输出显示如下:

Detected memory leaks!
Dumping objects ->
{147} normal block at 0x060A72F0, 4 bytes long.
 Data: <    > F0 D9 C2 0F 
Object dump complete.

如果我取消注释 'TEST_METHOD()' 中的行以在 147 位置设置断点。调试通常会在没有更多信息的情况下退出(日志 here)。

我正在使用 Visual Studio 2013 和 Visual C++ 本机单元测试项目。所以,我的问题是:

感谢您的任何意见。 贾尔达

编辑:正如@Hans Passant 所指出的,我已经尝试添加断点并观察断点变量,但都没有用,应用程序只是 returns 代码 0。如果我添加自己的断点和尝试观察变量,它表示未找到,如 here 所示。请注意,我不确定 VS 使用哪个 C++。

Edit2:由于有多个问题并且大部分都已解决,我将把这个问题标记为已解决问题,并将一个问题分别标记为未解决。

谢谢

Is the class constructor and destructor written OK??

它在技术上似乎是正确的,但它是用 'old fashioned' C++ 编写的。如果您将 data 成员更改为 std::vector<std::vector<float>>,那么内存管理将全部为您处理。你真的不应该用 newdelete.

编写新的 C++ 代码

The second leak deteciton - 4 bytes: what causes this and how to obtain better information about it?

CRT 可能需要自己为它没有解除分配的断点分配内存,因为断点需要在程序的生命周期内保持活动状态。

Does have to the block containint the 'Tested t;' end before '_CrtDumpMemoryLeaks();'?

是的,在 } 行调用了析构函数。这就是为什么还建议调用 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);,以便在调用所有自动析构函数后在程序退出时转储内存泄漏。

Am I using the leak detection right? Or is there a better way how to do this??

如果您使用的是 MSVC,则可以使用内置工具进行操作。如果您使用其他编译器,例如 clang,那么它们会附带自己的内存验证工具,如果您在 Linux 上 运行,那么您可以使用 valgrind 检测泄漏。但由于您使用的是 Microsoft 的编译器,因此使用他们的工具是有意义的。