#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,如上所示。
总起来讲,这段代码的作用就是防止内存泄露,减小程序编译开销的。
#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #endif的更多相关文章
- #ifdef _DEBUG
#ifdef _DEBUG virtual void AssertValid() const; //assert(断言)valid(有效的,正确的) virtual void Dump(CDumpCo ...
- 【转】#ifdef _DEBUG用法小结
原文地址:http://blog.csdn.net/shijizhisheng/article/details/1908054 1 #ifdef _DEBUG virtual void AssertV ...
- #ifdef _DEBUG/ #define new DEBUG_NEW/ #endif的作用
转载:https://blog.csdn.net/minghui_/article/details/80748142 转自:#ifdef _DEBUG #define new DEBUG_NEW #e ...
- #ifdef _DEBUG #define new DEBUG_NEW #endif的解释
转载:https://blog.csdn.net/sinat_20265495/article/details/51762738 在用vc时,利用AppWizard会产生如下代码:#ifdef _DE ...
- 史上最全条件编译解析 #ifdef #ifndef #undef #else #endif
C语言和C++语言程序中广泛存在着#ifdef或#ifndef等条件编译语句,本篇就系统介绍下他们的用法. 这几个宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分 ...
- static char定义的用法
static char *p是全局静态变量,char *p是临时变量,static定义的你在其他地方可以调用,而且是通用的,也就是说你在一个地方改了它的值,其他地方也就跟着改了,而char *p只是一 ...
- 关于语句#ifdef OS_GLOBALS #define OS_EXT #else #define OS_EXT extern #endif 的说明
声明全局变量使用的技术——摘自uC/OS-II中文版 以下是如何定义全局 变量.众所周知,全局变量应该是得到内存分配且可以被其他模块通过C 语言中extern 关键字调用的变量.因此,必须在 .C 和 ...
- C++编译错误syntax error : identifier 'THIS_FILE' 解决方法
你到代码里搜索 THIS_FILE看是不是它定义在别的头文件前面了,如果是,把它们的头文件紧跟到Stdafx.h后面 我遇到过这问题,这样搞定的 今天遇到个编译错误:..\vc98\include\n ...
- 关于THIS_FILE
VC++中本身就有内存泄漏检查的机制,可以在向导生成的支持MFC的工程中看到如下代码: #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE ...
随机推荐
- 《PHP中的Math函数》笔记
① abs() 绝对值; ② ceil() 向上取整; ③ floor() 向下取整; ④ fmod() 返回除法的浮点数余数; ⑤ getrandmax() 显示随机数最大的可能值; ⑥ is_fi ...
- C#接口的作用(经典)
C#接口是一个让很多初学C#者容易迷糊的东西,用起来好像很简单,定义接口,里面包含方法,但没有方法具体实现的代码,然后在继承该接口的类里面要实现接口的所有方法的代码,但没有真正认识到接口的作用的时候就 ...
- 有人要分享pjax吗?
安装 1.在 composer.json 的 require里 加入 "yuanchao/pjax-for-laravel-5": "dev-master" 2 ...
- HTML5 的一些小的整理吧
主要的就是一些HTML 5 API 的使用 也是借鉴别人的博客 ,和MDN(中文部分的还是能看的懂) 上面的一些东西 具体的代码在 有道云笔记里面也有. 先把总得列出来 1.Canvas绘图 学完这个 ...
- 如何在Linux中搭建禅道8.4.1(httpd+php+mysql)
1.安装httpd 命令:yum install httpd 然后一路y即可 2.安装php 命令:yum install php 3.安装php-mysql 命令:yum install php ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
- 编译器--__attribute__ ((packed))
1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法.这个功能是跟操作系统没关系,跟编译器有关,g ...
- javaScript事件(一)事件流
一.事件 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字.事件是javaScript和DOM之间的桥梁.你若触发,我便执行——事件发生,调用它的处理函数 ...
- Visual Studio高级调试技巧
1. 设置软件断点,运行到目标位置启动调试器 方法①:使用汇编指令(注:x64 c++不支持嵌入汇编) _asm 方法②:编译器提供的方法 __debugbreak(); 方法③:使用windows ...
- sk_buff封装和解封装网络数据包的过程详解
转自:http://www.2cto.com/os/201502/376226.html 可以说sk_buff结构体是Linux网络协议栈的核心中的核心,几乎所有的操作都是围绕sk_buff这个结构体 ...