原创: WINCE 内存泄露的检查(1) 对new/delete 或malloc/free在堆上申请的内存泄露的检查

这种方式的内存泄露的检查还是比较好办的,

首先重载 new/delete 或 malloc/free;

void* __cdecl operator new(size_t nSize,LPCSTR lpszFileName,int nLine);
void __cdecl operator delete(void *pvMem);

void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine);
void __cdecl operator delete[](void *);

 

并定义

#define DEBUG_NEW new(__FILE__, __LINE__)
#define DEBUG_DELETE delete(__FILE__, __LINE__)

并在所有的代码文件中定义

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

 

在程序中维护一个全局的链表或者二叉树,当使用new/malloc申请内存时候,就会进入我们重载的new或者malloc,这样就可以把申请内存的文件名和行号记下,然后再delete/free时把对应的记录删除掉,在程序退出的时候检查全局链表或者二叉树,如果为空呢就没有内存泄露,如果不为空呢就可以定位到引起内存泄露的文件和行号。

 

废话少说马上附代码

(注:下面代码中没有在申请的内存前后添加特殊标示用于判断堆损坏等情况,还是比较简陋,程序最后会附一个网上很有名的内存泄露检查代码(debugnew(debugnew.h/debugnew.cpp)

 

程序代码以及debugnew的代码请到http://download.csdn.net/source/1590036 下载

 

mem.h///

#ifndef _MEM_H_
#define _MEM_H_

#pragma once

#include <map>
#include <utility>

using namespace std;
#pragma warning(disable:4291)

#define DIM(A) sizeof(A)/sizeof(A[0])

typedef struct tag_MemoryInfo
{
 char tszFile[MAX_PATH];
 ULONG cchLine;
 size_t nMemSize;
}MemoryInfo;

#ifdef _DEBUG

extern map<DWORD,MemoryInfo> g_MemList;
void* __cdecl operator new(size_t nSize,LPCSTR lpszFileName,int nLine);
void __cdecl operator delete(void *pvMem);

void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine);
void __cdecl operator delete[](void *);

#define DEBUG_NEW new(__FILE__, __LINE__)
#define DEBUG_DELETE delete(__FILE__, __LINE__)

#endif
#endif // _MEM_H_

 

 

mem.cpp///

#include "stdafx.h"
#include "mem.h"

#ifdef _DEBUG
map<DWORD,MemoryInfo> g_MemList;
void* __cdecl operator new(size_t nSize,LPCSTR lpszFileName,int nLine)
{
 PVOID pVoid = ::operator new(nSize);
 MemoryInfo mem;
 mem.cchLine = nLine;
 mem.nMemSize = nSize;
 strcpy_s(mem.tszFile,DIM(mem.tszFile),lpszFileName);
 g_MemList[(DWORD)pVoid] = mem;
 return pVoid;
}

void __cdecl operator delete(void* p)
{
 DWORD nKeyword = (DWORD)p;
 if (!g_MemList.empty())
 {
  map<DWORD,MemoryInfo>::iterator iter= g_MemList.find(nKeyword);
  if (iter != g_MemList.end())
  {
   g_MemList.erase(iter);
  }
 }
 ::free(p);
}

void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine)
{
 PVOID pVoid = ::operator new(nSize);
 MemoryInfo mem;
 mem.cchLine = nLine;
 mem.nMemSize = nSize;
 strcpy_s(mem.tszFile,DIM(mem.tszFile),lpszFileName);
 g_MemList[(DWORD)pVoid] = mem;
 return pVoid;
}

void __cdecl operator delete[](void *p)
{
 DWORD nKeyword = (DWORD)p;
 if (!g_MemList.empty())
 {
  map<DWORD,MemoryInfo>::iterator iter= g_MemList.find(nKeyword);
  if (iter != g_MemList.end())
  {
   g_MemList.erase(iter);
  }
 }
 ::free(p);
}
#endif

 

其实这种方式引起的内存泄露完全可以通过智能指针来避免,并且智能指针还可以带来异常安全,智能指针例如标准库中的auto_ptr,但auto_ptr不是基于引用计数的所以不能用于标准库容器,对应要在容器中使用的智能指针可以通过采用Boost库中的共享指针或者自己写一个采用引用计数的智能指针(注:可以到http://download.csdn.net/source/1590077 下载笔者自己写的只能指针)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值