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

情况1:
#ifdef _DEBUG
virtual void AssertValid() const;                 //assert(断言)valid(有效的,正确的)
virtual void Dump(CDumpContext& dc) const;        //存储上下文
#endif

这两个函数是调试用的,第一个函数检查可用性,即是否有效。第二个函数如果未更改的话,最终调用的是Cwnd::Dump();输出窗口类名,标题名等一系列信息(在输出窗口中)。

#ifdef _DEBUG
#endif
这是条件编译,即如果有#define _DEBUG这两个函数会编译,否则忽略。当你用debug生成时(相对于release)开发环境则自动的加上这个宏定义,这两个函数有效。

情况2:
#ifdef _DEBUG                                   // 判断是否定义_DEBUG
#undef THIS_FILE                                // 取消THIS_FILE的定义
static char THIS_FILE[]=__FILE__;               // 定义THIS_FILE指向文件名
#define new DEBUG_NEW                           // 定义调试new宏,取代new关键字
#endif // 结束

如果定义了_DEBUG,表示在调试状态下编译,因此相应修改了两个符号的定义。
    THIS_FILE是一个char数组全局变量,字符串值为当前文件的全路径,这样在Debug版本中当程序出错时出错处理代码可用这个变量告诉你是哪个文件中的代码有问题。
    定义 _DEBUG后,由于定义了_DEBUG,编译器确定这是一个调试,编译#ifdef _DEBUG和#endif之间的代码。#undef 表示清除当前定义的宏,使得THIS_FILE无定义。
   __FILE__ 是编译器能识别的事先定义的ANSI C 的6个宏之一。
   DEBUG_NEW定位内存泄露并且跟踪文件名和行号。

情况3:
#ifdef _DEBUG                     //如果是debug状态
#undef THIS_FILE                  //清除THIS_FILE
static char THIS_FILE[]=__FILE__; //定义THIS_FILE为__FILE__(这是当前文件全路径名字)
#define new DEBUG_NEW //定义new为DEBUG_NEW(这个可以检测到内存泄露之类的问题,其实就是可以使用crt开头的那几个调试函数)
#endif

ANSI C 的6个宏:
__FILE__为预编译器常量,返回当前编译的文件名,还有比较常用的几个预编译器常量;
__LINE__编译器正在编译的文件的第几行;
__DATE__返回当前的日期Jul-20-2004;
__TIME__返回当前的时间hh:mm:ss; 
__TIMESTAMP__ 的预定义的编译器宏始终返回时间戳信息。在太平洋标准的时间内无论本地时间和CL.EXE 的运行位置在计算机上的时区。
__STDC__条件编译,意思是:如果定义了标准C或c++,那么编译这句话后面直到#endif以前的源代码。
_STDC__cplusplus这两个都是标准宏,_STDC_表示是是否符合标准C;_cplusplus表示是否是C++。

曾经一个解释说,多次使用__FILE__宏,虽然得到字符串的内容相同,但是可能地址不同,即同一个字符串常量多次用到时占用不同的地址,这样导致需要的内存增加了。为了检测内在泄露, Debug 版本的 new 附加上了调用 new 的文件名与调用所在的行号信息, 这是通过 __FILE__ 和 __LINE__ 来实现的, 这两个属于预定义的内部宏, 而之所以要用 THIS_FILE 来代替 __FILE__, 是为了减少程序大小: 如果你在一个文件中有 10000 次对 new 的调用, 那么会生成 10000 个当前文件名的常量字符串(第一个都是由 __FILE__ 宏扩展而来的), 最后生成的目标文件会很大, 而用 THIS_FILE 来代替, 当前文件名只有一份, 传递文件名使用 THIS_FILE 指针就可以了。

__FILE__和__LINE__一样都是编译器定义的宏。当碰到__FILE__时,编译器会把__FILE__替换成一个字符串,这个字符串就是当前在编译的文件的路径名。在DEBUG_NEW的定义中没有直接使用__FILE__,而是用了THIS_FILE,其目的是为了减小目标文件的大小。假设在某个cpp文件中有100处使用了new,如果直接使用__FILE__,那编译器会产生100个常量字符串,这100个字符串都是这个cpp文件的路径名,显然十分冗余。如果使用THIS_FILE,编译器只会产生一个常量字符串,那100处new的调用使用的都是指向常量字符串的指针。
   
    在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,如上所示。

总起来讲,这段代码的作用就是防止内存泄露,减小程序编译开销的。

时间: 2024-11-13 06:16:47

#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #endif的相关文章

#ifdef _DEBUG用法小结

1#ifdef _DEBUG virtual void AssertValid() const; //assert(断言)valid(有效的,正确的)virtual void Dump(CDumpContext& dc) const; //存储上下文#endif这两个函数是调试用的,第一个函数检查可用性,即是否有效 第二个函数如果未更改的话,最终调用的是Cwnd::Dump(); 输出窗口类名,标题名等一系列信息(在输出窗口中) #ifdef _DEBUG #endif 这是条件编译,即如果有#

VS之XML文件操作

XML,可扩展的标识语言(eXtensible Markup Language),具有多种优势,所以现在被广泛使用,本文通过一个简单的例子来实现对XML文件的保存和读取操作. 使用工具:VS2008 使用语言:C++ 开发步骤: 1.新建对话框程序 2.添加XML相关类 该类摘自网络 Markup.h // Markup.h: interface for the CMarkup class. // // Markup Release 8.2 // Copyright (C) 1999-2006

(转)从内存管 理、内存泄漏、内存回收探讨C++内存管理

http://www.cr173.com/html/18898_all.html 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对 C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,因此要想成为C++高手,内存管理一关是必须要过的,除非放弃 C++,转到Java或者.NET,他们的内存管理基本是自动的,当然你也放弃了自由和对内存的支配权,还放弃了C++超绝的性能

vc实现透明位图,透明背景

vc实现透明位图,透明背景 我们在进行程序的界面设计时,常常希望将位图的关键部分,也既是图像的前景显示在界面上,而将位图的背景隐藏起来,将位图与界面很自然的融合在一起,本文介绍了透明位图的制作知识,并将透明位图在一个对话框中显示了出来. 一.实现方法 绘制"透明"位图是指绘制某一位图中除指定颜色外的其余部分,我们称这种颜色为"透明色".通过将位图的背景色指定为"透明色",在绘制时,不绘制这部分背景,而仅绘制图像,这样就可以将位图中图像透明地绘制到

CGridCtrl 添加button (CGridCellButton类)

#ifndef __GRID_CELL_BUTTON__ #define __GRID_CELL_BUTTON__ #include "../GridCtrl_src/GridCell.h" class CGridCellButton : public CGridCell { friend class CGridCtrl; DECLARE_DYNCREATE(CGridCellButton) public: CGridCellButton(void); ~CGridCellButton

(转载)DLL动态链接库编程入门之三:MFC规则DLL(上)

上一节中讲解了非MFC DLL,本节将介绍如何创建MFC规则DLL及使用MFC规则DLL的方法. 一.MFC规则DLL概述 MFC规则DLL的概念体现在两方面: (1)它是MFC的 "是MFC的"意味着可以在这种DLL的内部使用MFC: (2)它是规则的 "是规则的"意味着它不同于MFC扩展DLL,在MFC规则DLL的内部虽然可以使用MFC,但是其与应用程序的接口不能是MFC.而MFC扩展DLL与应用程序的接口可以是MFC,可以从MFC扩展DLL中导出一个MFC类的

从位图文件生成任意形状的窗口

http://hi.baidu.com/aidfan/blog/item/89547c4336566a1d9213c67a.html 有许多的软件的界面十分地漂亮,不仅窗口的客户区绘制得十分精细,连窗口的外形也是“奇形怪状”的,比如 Office 2000助手.Media Player 7.MediaRing Talk等等,连Winamp在应用了某些皮肤之后也不再是标准的矩形窗口,下图也是一个不规则的窗口. 那么,我们在编程的时候如何实现这一效果呢? 在众多的Windows API函数中,有一个

半透明信息显示浮动窗口的实现

快乐鹦鹉 原文 半透明信息显示浮动窗口的实现    实现目的 在一些画图软件中,经常需要向用户展示鼠标移动到的位置的对象的一些参数信息.此时,完成一个交互性友好的信息显示界面就相当的重要了.因为一个软件的好坏,在用户的眼中,第一感觉甚至是第一重要的就是视觉效果和可操作性.当然,软件本身的稳定性和效率也很重要.特别对于产品性的软件,在用户展示时,一个优秀的界面效果可以大大加深软件在用户心里的印象分.        功能简介 本功能是作者根据自身软件在用户实际使用过程中对交互性的更高要求而开发的.浮

C++内存管理(超长,例子很详细,排版很好)

[导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,因此要想成为C++高手,内存管理一关是必须要过的,除非放弃C++,转到Java或者.NET,他们的内存管理基本是自动的,当然你也放弃了自由和对内存的支配权,还放弃了C++超绝的性能.本期专题将从内存管理.内存泄漏.内存回收这三个方面来探讨C++内存管理问题