内存调试#define new DEBUG_NEW

62 篇文章 10 订阅

 在用vc时,利用AppWizard会产生如下代码:

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

对于

#define new DEBUG_NEW
首先看msdn的解释:

Assists in finding memory leaks. You can use DEBUG_NEW everywhere in your program that you would ordinarily use the new operator to allocate heap storage.

In debug mode (when the _DEBUG symbol is defined), DEBUG_NEW keeps track of the filename and line number for each object that it allocates. Then, when you use the CMemoryState::DumpAllObjectsSince member function, each object allocated with DEBUG_NEW is shown with the filename and line number where it was allocated.

To use DEBUG_NEW, insert the following directive into your source files:

#define new DEBUG_NEW

Once you insert this directive, the preprocessor will insert DEBUG_NEW wherever you use new, and MFC does the rest. When you compile a release version of your program, DEBUG_NEW resolves to a simple new operation, and the filename and line number information is not generated.

再查看定义:

#ifdef _DEBUG

void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#define DEBUG_NEW new(THIS_FILE, __LINE__)

#else

#define DEBUG_NEW new

#endif

这样就很清楚了,当在debug模式下时,我们分配内存时的new被替换成DEBUG_NEW,而这个DEBUG_NEW不仅要传入内存块的大小,还要传入源文件名和行号,这就有个好处,即当发生内存泄漏时,我们可以在调试模式下定位到该问题代码处。若删掉该句,就不能进行定位了。而在release版本下的new就是简单的new,并不会传入文件名和行号。

因此,我们在开发代码阶段,保留上述代码是值得的。

 

 

 

#ifdef _DEBUG

#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
(1) 在 MFC 中,可以使用 DEBUG_NEW 宏代替 new 运算符来帮助定位内存泄漏。在程序的
“Debug”版本中,DEBUG_NEW将为所分配的每个对象跟踪文件名和行号。当编译程序的
“Release”版本时,DEBUG_NEW 将解析为不包含文件名和行号信息的简单 new 操作。因此,
在程序的“Release”版本中不会造成任何速度损失。
    如果不想重写整个程序来使用 DEBUG_NEW代替new,则可以在源文件中定义下面的宏:
#define new DEBUG_NEW 当进行对象转储时,用 DEBUG_NEW分配的每个对象均将显示被分
到的文件和行号,使您可以查明内存泄漏源。
   
MFC 框架的“Debug”版本自动使用 DEBUG_NEW,但代码不自动使用它。如果希望利用 DEBUG_NEW 的好处,则必须显式使用 DEBUG_NEW 或 #define new DEBUG_NEW,如上所示。
(2)__FILE__和__LINE__都是编译器定义的宏。当碰到__FILE__时,编译器会把__FILE__替换成一个字符串,这个字符串就是当前在编译的文件的路径名。在DEBUG_NEW的定义中没有直接使用__FILE__,而是用了THIS_FILE,其目的是为了减小目标文件的大小。假设在某个cpp文件中有100处使用了new,如果直接使用__FILE__,那编译器会产生100个常量字符串,这100个字符串都是这个cpp文件的路径名,显然十分冗余。如果使用THIS_FILE,编译器只会产生一个常量字符串,那100处new的调用使用的都是指向常量字符串的指针。
(3) 这是dubug时输出出错在文件文件位置信息的一些宏.
THIS_FILE
Remarks
The information is used by the ASSERT and VERIFY macros. The Application Wizard and code wizards place the macro in source code files they create.
Example
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// __FILE__ is one of the six predefined ANSI C macros that the compiler recognizes.
 
另外:
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
这两个函数是调试用的,第一个函数检查可用性,即是否有效
第二个函数如果未更改的话,
最终调用的是Cwnd::Dump(); 输出窗口类名,标题名等一系列信息(在输出窗口中)
 
 
 

About DEBUG_NEW

一、在调试模式下,new操作符号通过宏定义转换成了调试版本。

在文件头经常可以发现以下语句:

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

其中,将new定义为DEBUG_NEW

二、DEBUG_NEW的处理

调试版本的new操作函数:void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);

宏替换:#define DEBUG_NEW new(THIS_FILE, __LINE__) //文件名、行号被传入,供调试输出。

实际代码如下:

void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}
//分配内存
void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
{
#ifdef _AFX_NO_DEBUG_CRT
UNUSED_ALWAYS(nType);
UNUSED_ALWAYS(lpszFileName);
UNUSED_ALWAYS(nLine);
return ::operator new(nSize);
#else
void* pResult;
#ifdef _AFXDLL
_PNH pfnNewHandler = _pfnUninitialized;
#endif
for (;;)
{
pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine);
if (pResult != NULL)
return pResult;
#ifdef _AFXDLL
if (pfnNewHandler == _pfnUninitialized)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
pfnNewHandler = pState-> m_pfnNewHandler;
}
if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
break;
#else
if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
break;
#endif
}
return pResult;
#endif
}
#endif //_DEBUG

 

DEBUG_NEW

  #define new DEBUG_NEW

  说明:

  帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下(但定义了一个DEBUG符号),DEBUG_NEW为它分配的每个对象记录文件名和行号。然后,在用户使用CMemoryState::DumpAllObjectSince成员函数时,每个以DEBUG_NEW分配的对象分配的地方显示出文件名和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令: #define new DEBUG_NEW 一旦用户插入本指令,预处理程序将在使用new的地方插入DEBUG_NEW,而MFC作其余的工作。但用户编译自己的程序的一个发行版时,DEBUG_NEW便进行简单的new操作,而且不产生文件名和行号消息。

 

以下是MSDN中的内容:   
在   MFC   中,可以使用   DEBUG_NEW   宏代替   new   运算符来帮助定位内存泄漏。在程序的“Debug”版本中,DEBUG_NEW   将为所分配的每个对象跟踪文件名和行号。当编译程序的“Release”版本时,DEBUG_NEW   将解析为不包含文件名和行号信息的简单   new   操作。因此,在程序的“Release”版本中不会造成任何速度损失。   
如果不想重写整个程序来使用   DEBUG_NEW   代替   new,则可以在源文件中定义下面的宏:   
#define   new   DEBUG_NEW  
当进行对象转储时,用   DEBUG_NEW   分配的每个对象均将显示被分配到的文件和行号,使您可以查明内存泄漏源。   
MFC   框架的“Debug”版本自动使用   DEBUG_NEW,但代码不自动使用它。如果希望利用   DEBUG_NEW   的好处,则必须显式使用   DEBUG_NEW   或   #define   new,如上所示。   

 
 
测试代码:
 
#include "stdafx.h" 
#include "afx.h" 
#include "iostream.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 
int main(int argc, char* argv[]) 
{ 
	char *sBuf; 
	int *aiBuf; 
	CString *sText; 

   
  sBuf=new char[20]; 
  aiBuf=new int[20]; 

  sText=new CString("deljklggl mbjgv afda"); 
  return 0; 
} 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值