C++中内存泄漏的检查与定位

本文简述了使用C++在Windows平台下检查和定位内存泄漏的方法,包括利用<crtdbg.h>头文件中的函数,如_CrtDumpMemoryLeaks()和_CrtSetDbgFlag()等,通过设置断点和调整内存分配行为来精确识别内存泄漏位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文仅仅是一些简短讲述一下,关于C++在Windows平台下内存泄漏内存泄漏的检查与定位。请参阅《最快速度找到内存泄漏》

 

在Windows平台下,可以借助头文件<crtdbg.h>中定义的一以下几个函数来完成。

_CrtDumpMemoryLeaks();
// 置于main函数最后,打印内存泄露报告

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
// 置于main函数开头(当当前程序没有统一退出点时)

long _CrtSetBreakAlloc(long lBreakAlloc);
//用于在给定内存分配操作时停止当前程序


以下是_CrtDumpMemoryLeaks()的详细代码。(仅在Debug版本下有效)

#include <crtdbg.h>


void main()  
{    
    int* pLeak = new int[10];

    pLeak = nullptr;

    _CrtDumpMemoryLeaks(); 
} 


这样在当前程序执行结束后,在Vistual Studio的Output窗口中会输出如下信息:

Detected memory leaks! 
Dumping objects -> 
c:/work/test.cpp(186) : {52} normal block at 0x003C4410, 40 bytes long. 
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD  
Object dump complete.

 

以上信息似乎仅仅告诉了我们内存泄漏发生了,但依旧难以定为具体的内存泄漏的位置。

 

以下是改进后的版本:

#define _CRTDBG_MAP_ALLOC
// 用于将malloc和free函数重定向至DEBUG版本,使之能输出对应的源文件及行号。

#include <crtdbg.h>

#ifdef _DEBUG   
#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)   
#endif
// 重定向new关键字,否则对于所有的new操作,依旧无法正确输出对应的源文件及行号。

void main()  
{    
    int* pLeak = new int[10];

    pLeak = nullptr;

    _CrtDumpMemoryLeaks(); 
}


但有些时候,这依旧很难帮助我们找到具体的内存泄漏点。

我们注意到,在以上内存泄漏报告中有一个奇怪的信息({52}),其表示是第52次内存分配时,所分配的内存未被回收。

方法long _CrtSetBreakAlloc(long lBreakAlloc)可以使程序停止在指定的内存分配操作处(即:第52次内存分配)。

#include <crtdbg.h>


void main()  
{
    _CrtSetBreakAlloc(52);

    int* pLeak = new int[10];

    pLeak = nullptr;

    _CrtDumpMemoryLeaks(); 
}


再次在VS中执行上述代码,程序会在指定处停止并进入调试状态。通过查看函数调用堆栈,便可以精确定位出错的代码行,及当时的程序运行状态。

在这里,还有一点要注意的是C++的全局变量,一些全局变量的初始化会在进入main方法前就发生了。这种情况下,上述方法依旧无效。详见下例:

struct MyCls
{
    string SubExprStr;
};


MyCls g_MyCls = {
    string("Hello world!")
};

 

上述代码中,g_MyCls对象实例的初始化在进入main方法前就完成了。在这种情况下,可以通过设置条件断点来完成。具体如下:

// file 'dbgheap.c'

extern "C" static void * __cdecl _heap_alloc_dbg_impl(
        size_t nSize,
        int nBlockUse,
        const char * szFileName,
        int nLine,
        int * errno_tmp
        )
{
        // ...

        /* lock the heap
         */
        _mlock(_HEAP_LOCK);
        __try {

            // ...

            /* break into debugger at specific memory allocation */
            if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)
                _CrtDbgBreak();


在以下行处设置条件断点,在变量lRequest等于给定内存分配次数时停止执行。

if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)


上述方法在本人的机器(Windows 7  VS2010)上测试有效,暂时未在其它情况下验证过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值