VC++6.0中内存泄漏检测

  
VC ++6.0 中内存泄漏检测
 
摘自:VC知识库BLOG-周星星 网址:blog.vckbase.com/bruceteen/

C++ 代码而言 , 内存泄漏问题虽然有诸多方法避免 , 但实际代码编写的时候 , 或出于自信或出于复杂性的考虑 , 常常还会用到原始的 operator new, 这不可避免的会带来内存泄漏的可能 , 不久前本人因为违反了 " 可用于被多态继承的基类其析构函数应当有 virtual 修饰 " 的法则 ( 一不小心就忘了写 virtual ^_^ ), 导致了内存泄漏 , 因此我觉得出于安全考虑 , 在代码中加入内存泄漏检查机制还是很必要的 , 也因为这次的内存泄漏事件促使我写出这一篇文章 .

VC++
中本身就有内存泄漏检查的机制 , 你可以在向导生成的支持 MFC 的工程中看到如下代码 :
  #ifdef _DEBUG
  #define new DEBUG_NEW
  #undef THIS_FILE
  static char THIS_FILE[] = __FILE__;
  #endif
通过它们 , 你能非常容易的发现代码中的内存泄漏 , 但是如果手工将这个功能移植到非 MFC 工程中去是很繁琐的一件事 , 另外它还有一个 bug, 在多线程并发调用这个 DEBUG_NEW 时会导致系统级错误 , 因此本人在此重写了这个功能 , 将以下的 debug_new.h debug_new.cpp 添加到工程中 , 并在需要检测的 cpp #include "debug_new.h" main 中一开始处加入 REG_DEBUG_NEW 宏即可 .

1. debug_new.h 源代码
/************************************************************************/
/* comment:  
此文件与 debug_new.cpp 配合使用 , 用于在调试期发现内存泄漏      */
/*          
仅在 VC++ 编译器中适用 ( 包括 Intel C++, 因为它使用了相同的库 )   */
/*
作者 :     周星星 http://blog.vckbase.com/bruceteen/                  */
/*
版权申明 : , 可任意 使用 , 修改 发布                                 */
/************************************************************************/

/* sample

#include <iostream>
#include "debug_new.h" // +
using namespace std;

int main( void )
{
    REG_DEBUG_NEW; // +

    char* p = new char[2];

    cout << "--End--" << endl;
    return 0;
}

VC++ IDE 中按 F5 调试运行将会在 Output 窗口的 Debug 页看到类似如下的提示 :
Dumping objects ->
d:/test.cpp(10) : {45} normal block at 0x003410C8, 2 bytes long.
Data: <  > CD CD
Object dump complete.

如果不出现如上提示请 Rebuild All 一次 .

*/


#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_

    #ifdef _DEBUG

        #undef new
        extern void _RegDebugNew( void );
        extern void* __cdecl operator new( size_t, const char*, int );
        extern void __cdecl operator delete( void*, const char*, int);
        #define new new(__FILE__, __LINE__)
        
        #define REG_DEBUG_NEW _RegDebugNew();

    #else

        #define REG_DEBUG_NEW

    #endif // _DEBUG

#endif // _DEBUG_NEW_H_

2. debug_new.cpp
源代码
/************************************************************************/
/* comment:  
此文件与 debug_new.h 配合使用 , 用于在调试期发现内存泄漏        */
/*          
仅在 VC++ 编译器中适用 ( 包括 Intel C++, 因为它使用了相同的库 )   */
/*
作者 :     周星星 http://blog.vckbase.com/bruceteen/                  */
/*
版权申明 : , 可任意 使用 , 修改 发布                                 */
/************************************************************************/

//#include "debug_new.h"

#ifdef _DEBUG

#include <windows.h>
#include <crtdbg.h>

class _CriSec
{
    CRITICAL_SECTION criSection;
public:
    _CriSec()    { InitializeCriticalSection( &criSection ); }
    ~_CriSec()   { DeleteCriticalSection( &criSection );     }
    void Enter() { EnterCriticalSection( &criSection );      }
    void Leave() { LeaveCriticalSection( &criSection );      }
} _cs;

void _RegDebugNew( void )
{
    _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF );
}
void* __cdecl operator new( size_t nSize, const char* lpszFileName, int nLine )
{
    // comment 1: MFC
中提供的 debug new 虽然加了锁 , 但我在实际测试的时候发现多线程并发
    //            
调用的时候还是抛出了系统错误 , 所以我在这里加了一个线程互斥量 .
    // comment 2: debug new
debug delete 之间需不需要互斥我并不知道 , 保险起见 , 我同样
    //            
加了线程互斥量 .
    // comment 3:
按照 C++ 标准规定 , operator new 失败后应当调用 set_new_handler 设置的
    //            
函数 , 但是 MSDN 中却说 " 头文件 new 中的 set_new_handler stub , 而应该使
    //            
用头文件 new.h 中的 _set_new_handler", 这简直是滑天下之大稽 .
    //            
以下是 VC++6.0 中的 set_new_handler 定义 :
    //                new_handler __cdecl set_new_handler( new_handler new_p )
    //                {
    //                    assert( new_p == 0 ); // cannot use stub to register a new handler
    //                    _set_new_handler( 0 );
    //                    return 0;
    //                }
    //            
所以我也无计可施 , 只能舍弃 set_new_handler 的作用 .

    _cs.Enter();
    void* p = _malloc_dbg( nSize, _NORMAL_BLOCK, lpszFileName, nLine );
    _cs.Leave();
    return p;
}
void __cdecl operator delete( void* p, const char* /*lpszFileName*/, int /*nLine*/ )
{
    _cs.Enter();
    _free_dbg( p, _CLIENT_BLOCK );
    _cs.Leave();
}

#endif

3.
事例代码
#include <iostream>
#include "debug_new.h"
using namespace std;

int main( void )
{
    REG_DEBUG_NEW;

    char* p = new char[2];
    p[0] = 'A';
    p[1] = 'B';

    cout << "--End--" << endl;
    return 0;
}

4.
结果输出
VC++ IDE 中按 F5 调试运行将会在 Output 窗口的 Debug 页看到类似如下的提示 :
……
Dumping objects ->
d:/test.cpp(10) : {45} normal block at 0x003410C8, 2 bytes long.
Data: <AB> 41 42
Object dump complete.
……
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值