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++ 本机单元测试项目。所以,我的问题是:
- class构造函数和析构函数写的好吗??
- 第二个泄漏检测 - 4 字节:是什么原因造成的以及如何获得更好的信息?即:为什么断点不起作用?
- 是否必须包含 'Tested t;' 在“_CrtDumpMemoryLeaks();”之前结束的块?
- 我使用的泄漏检测对吗?或者有更好的方法吗??
感谢您的任何意见。
贾尔达
编辑:正如@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>>
,那么内存管理将全部为您处理。你真的不应该用 new
和 delete
.
编写新的 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 的编译器,因此使用他们的工具是有意义的。
我想开始使用 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++ 本机单元测试项目。所以,我的问题是:
- class构造函数和析构函数写的好吗??
- 第二个泄漏检测 - 4 字节:是什么原因造成的以及如何获得更好的信息?即:为什么断点不起作用?
- 是否必须包含 'Tested t;' 在“_CrtDumpMemoryLeaks();”之前结束的块?
- 我使用的泄漏检测对吗?或者有更好的方法吗??
感谢您的任何意见。 贾尔达
编辑:正如@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>>
,那么内存管理将全部为您处理。你真的不应该用 new
和 delete
.
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 的编译器,因此使用他们的工具是有意义的。