C++ 内存泄漏,无法找到源

C++ 内存泄漏,无法找到源,c++,memory-leaks,mfc,kinect,C++,Memory Leaks,Mfc,Kinect,我有一个很大的内存泄漏,我需要一些帮助来找出它的来源。首先,关于代码的一些理论: 这是一个Kinect项目。它是在MS Visual Studio 2012中构建的MFC项目,使用Direct2D将图像显示在屏幕上。 从Kinect 1切换到Kinect 2时会出现此问题。然后,除主对象之外的每个对象都会被解构/释放,并将指针设为NULL。 这包括: 所有Direct2D对象工厂、渲染目标、位图、笔刷等 带线的Kinect facetracker 带线的kinect对象。 对于每个新关键字,我都

我有一个很大的内存泄漏,我需要一些帮助来找出它的来源。首先,关于代码的一些理论:

这是一个Kinect项目。它是在MS Visual Studio 2012中构建的MFC项目,使用Direct2D将图像显示在屏幕上。 从Kinect 1切换到Kinect 2时会出现此问题。然后,除主对象之外的每个对象都会被解构/释放,并将指针设为NULL。 这包括:

所有Direct2D对象工厂、渲染目标、位图、笔刷等 带线的Kinect facetracker 带线的kinect对象。 对于每个新关键字,我都在析构函数中使用delete关键字,因此我没有对没有用new初始化的指针进行析构函数。我关闭了所有线程处理程序并将它们设置为NULL

//Should delete a pointer and set it to NULL
void FaceTracking::Release()
{
    faceTrackingResult = NULL;
    nuiPresent = NULL;
    ColorBuffer = NULL;
    DepthBuffer = NULL;
}
现在我有一个内存泄漏,我需要一些帮助来找到它。我从使用

在初始化之后,我有一些输出:

Dumping objects ->
{402} normal block at 0x1531E8F0, 28 bytes long.
 Data: <<       @       > 3C 07 06 00 F0 00 00 00 40 01 00 00 00 05 00 00 
{401} normal block at 0x152F6CD8, 96 bytes long.
 Data: <    >           > 00 CD CD CD 3E 07 06 00 D0 04 00 00 D8 17 00 00 
{400} normal block at 0x03EA0040, 1229064 bytes long.
 Data: <R            E, > 52 07 06 00 B8 A9 13 00 D0 87 D0 00 18 45 2C 15 
{396} normal block at 0x152C9EA0, 20 bytes long.
 Data: <                > 80 F9 89 00 01 00 00 00 01 00 00 00 01 00 00 00 
c:\users\work\documents\github\kinectmain\testmfc\main.cpp(148) : {305} client block at 0x152CF618, subtype c0, 8 bytes long.
a CFont object at $152CF618, 8 bytes long
{295} normal block at 0x152CFC20, 24 bytes long.
 Data: <X   ( , X       > 58 07 CC 00 28 F8 2C 15 58 07 CC 00 00 00 CD CD 
{284} normal block at 0x152CF828, 24 bytes long.
 Data: <X   X     ,     > 58 07 CC 00 58 07 CC 00 20 FC 2C 15 01 00 CD CD 
{206} normal block at 0x00CD0588, 12 bytes long.
 Data: <    @       > B0 04 CD 00 40 05 CD 00 B8 A9 13 00 
{205} normal block at 0x00CD0540, 12 bytes long.
 Data: <            > 88 05 CD 00 B0 04 CD 00 18 BE 13 00 
{204} normal block at 0x00CD04F8, 8 bytes long.
 Data: <        > EC F3 89 00 00 00 00 00 
{203} normal block at 0x00CD04B0, 12 bytes long.
 Data: <@           > 40 05 CD 00 88 05 CD 00 CD CD CD CD 
{202} normal block at 0x00CD0468, 12 bytes long.
 Data: <    H       > 08 FE CC 00 48 A5 CC 00 18 BE 13 00 
{201} normal block at 0x00CCFE08, 12 bytes long.
 Data: <H   h       > 48 A5 CC 00 68 04 CD 00 B8 A9 13 00 
{200} normal block at 0x00CCA590, 8 bytes long.
 Data: <        > FC A4 CC 00 00 00 00 00 
{199} normal block at 0x00CCA548, 12 bytes long.
 Data: <h           > 68 04 CD 00 08 FE CC 00 CD CD CD CD 
c:\users\work\documents\github\kinectmain\testmfc\main.cpp(163) : {198} normal block at 0x00CCA4F8, 16 bytes long.
 Data: <R       H       > 52 07 06 00 90 A5 CC 00 48 A5 CC 00 02 00 00 00 
{188} normal block at 0x00CC07B0, 8 bytes long.
 Data: <        > 9C FB A1 00 00 00 00 00 
{187} normal block at 0x00CC0758, 24 bytes long.
 Data: <( , ( ,   ,     > 28 F8 2C 15 28 F8 2C 15 20 FC 2C 15 01 01 CD CD 
Object dump complete.
0 bytes in 0 Free Blocks.
1229392 bytes in 17 Normal Blocks.
13498 bytes in 73 CRT Blocks.
0 bytes in 0 Ignore Blocks.
8 bytes in 1 Client Blocks.
Largest number used: 1245916 bytes.
Total allocations: 2504946 bytes.
即使在程序关闭之前我不会调用destroyWindow

任何关于原因的提示、建议或提示,或者我可以使用什么工具来找到原因,都会非常棒

Kinect类中的unInit方法肯定是内存泄漏的来源。每个字段都设置为null,而不首先删除指向的对象(如果有的话)。我还发现至少有一个方法返回指向新对象selectKinect的指针。除非仔细管理这些对象,否则它们也将是内存泄漏的来源

<>你可能想考虑使用一个库来帮助你进行内存管理。Boost的共享指针非常有用

#include <boost/shared_ptr.hpp>

using boost::shared_ptr;

shared_ptr<Kinect> kinect(new Kinnect);

kinect->SomeMethodOnKinnect();
Kinect类中的unInit方法肯定是内存泄漏的来源。每个字段都设置为null,而不首先删除指向的对象(如果有的话)。我还发现至少有一个方法返回指向新对象selectKinect的指针。除非仔细管理这些对象,否则它们也将是内存泄漏的来源

<>你可能想考虑使用一个库来帮助你进行内存管理。Boost的共享指针非常有用

#include <boost/shared_ptr.hpp>

using boost::shared_ptr;

shared_ptr<Kinect> kinect(new Kinnect);

kinect->SomeMethodOnKinnect();

{}括号中的数字是分配顺序号。如果您的程序是完全确定的,并且每次都做完全相同的事情,那么这些数字在一次运行到下一次运行时应该保持不变

在这种情况下,你可以使用这个技巧。将以下代码添加到主函数的顶部:

long lBreakAlloc = 0;
if ( lBreakAlloc > 0 )
{
    _CrtSetBreakAlloc( lBreakAlloc );
}
然后在if语句上设置断点并启动程序。当它在if停止时,更改lBreakAlloc的值以匹配泄漏内存的第一块的分配顺序号,然后让程序继续


当它到达分配内存块的点时,嘿,普雷斯托!它将在调试器中停止,您可以确切地看到哪个分配没有被释放。

括号中的数字是分配顺序号。如果您的程序是完全确定的,并且每次都做完全相同的事情,那么这些数字在一次运行到下一次运行时应该保持不变

在这种情况下,你可以使用这个技巧。将以下代码添加到主函数的顶部:

long lBreakAlloc = 0;
if ( lBreakAlloc > 0 )
{
    _CrtSetBreakAlloc( lBreakAlloc );
}
然后在if语句上设置断点并启动程序。当它在if停止时,更改lBreakAlloc的值以匹配泄漏内存的第一块的分配顺序号,然后让程序继续


当它到达分配内存块的点时,嘿,普雷斯托!它将在调试器中停止,您可以准确地看到哪个分配没有被释放。

注意,一些输出显示文件名和行号,有时还显示类名?请注意,有些输出显示文件名和行号,有时还显示类名?开始看吧,我给出了错误的链接,现在修复了,大部分unInit方法现在是析构函数的一部分,在设置为NULL之前有一个delete函数。但我仍然想知道,什么是正确的做法?大多数指针都没有用new关键字初始化,在将它们设置为NULL之前是否仍需要使用delete?如果指针不为NULL,则必须始终删除该指针以及指向该对象的最后一个指针。有时库方法会创建新对象,并将处理对象的方式和时间留给您。这就是C中的fopen所做的,虽然应该使用fclose来释放内存。好的!根据你的提示,我已经修复了很多漏洞,但是如果你想和我一起思考的话,还有一点:这里的来源:。我现在已经正确地销毁了我认为的每个指针,现在我正在查看非指针对象。我也需要摧毁它们吗?或者,当它们超出作用域时,它们会被清除吗?我给出了错误的链接,现在已修复,大部分unInit方法现在是析构函数的一部分,并且在设置为NULL之前有一个delete函数。但我仍然想知道,什么是正确的做法?大部分
se指针未使用new关键字初始化,在将其设置为NULL之前是否仍需要使用delete?如果指针不为NULL,则必须始终删除该指针以及指向该对象的最后一个指针。有时库方法会创建新对象,并将处理对象的方式和时间留给您。这就是C中的fopen所做的,虽然应该使用fclose来释放内存。好的!根据你的提示,我已经修复了很多漏洞,但是如果你想和我一起思考的话,还有一点:这里的来源:。我现在已经正确地销毁了我认为的每个指针,现在我正在查看非指针对象。我也需要摧毁它们吗?或者当它们超出范围时会被清理吗?我是OP。我的问题是:这对非MFC对象有效吗?因为我不仅使用MFC,例如,我还使用Direct2D和Kinect。对不起,我没有注意到你是OP。是的,它也适用于非MFC对象。只要您链接到调试CRT,您就可以在任何分配中使用此方法。我现在有以下情况:-当我从kinect A更改为kinect B时出现45 MB内存泄漏-每次kinect析构函数运行时都会运行的转储。此memoryState在析构函数的最开始处执行检查点,并在最后执行转储。因此,它将打印所有未被正确破坏的对象。在该运行中,大约有10个对象从未被破坏,这是正确的:在程序结束之前,这些对象不应该被破坏。始终使用相同的代码,将它们全部检出。所以我有一个45 MB的漏洞,不知道它来自哪里。有什么想法吗?我是OP。我的问题是:这对非MFC对象有效吗?因为我不仅使用MFC,例如,我还使用Direct2D和Kinect。对不起,我没有注意到你是OP。是的,它也适用于非MFC对象。只要您链接到调试CRT,您就可以在任何分配中使用此方法。我现在有以下情况:-当我从kinect A更改为kinect B时出现45 MB内存泄漏-每次kinect析构函数运行时都会运行的转储。此memoryState在析构函数的最开始处执行检查点,并在最后执行转储。因此,它将打印所有未被正确破坏的对象。在该运行中,大约有10个对象从未被破坏,这是正确的:在程序结束之前,这些对象不应该被破坏。始终使用相同的代码,将它们全部检出。所以我有一个45 MB的漏洞,不知道它来自哪里。有什么想法吗?