当前位置:C++技术网 > 资讯 > VS系列编译器调试版本与发布版本的区别详解

VS系列编译器调试版本与发布版本的区别详解

更新时间:2016-01-07 23:55:02浏览次数:1+次

微软VS系列编译器,有两个版本,Debug版本与Release版本,那么这两个版本的不同在哪里?分别执行什么样的?编译器在内存中会维护一张关于#define的表结构。这里只是添加一个表项叫DEBUG,没有内容。在VC编译器里,#define DEBUG是内嵌代码,编译器已经为我们准备好了,按照我们正常的理解,在DEBUG后面应该有东西啊,要不然怎么代替DEBUG。其实我们已经知道了,DEBUG与NULL相等,你可以试试,写个代码尝试下

#define test
#include "iostream.h"
void main()
{
cout << test  << endl;
}
那么他的作用是什么呢?
这是常用的一个小技巧。在调试代码的阶段,保留#define DEBUG这一行,后面的#if defined(DEBUG)部分的代码就可以起作用,打印出一些有助于调试的信息。等到出release版的时候,就可以把#defined DEBUG这一行删掉,或者改成#undef  DEBUG,后面的那段代码就不会被编译,也就不会打印call times这些东西了。在VC编译器下,经常出现,VC中有DEBIG和NDEBUG是微软定义好的,在debug版本编译器下,编译器会默认定义了DEBUG这个宏;
在release版本下,编译器会默认定义宏NDEBUG,所以最好不要自己把DEBUG与NDEBUG宏定义成其他意思。这样就可以利用


#ifdefDEBUG
/****做debug下要做的事*****
#else
/**做release版本下的事*******/

这样做的好处是无论在debug下还是release下,可以用同一个代码。
下面是C语言实现原理:

#define DEBUG
main()
{
#ifdef DEBUG
    printf("Debugging\n");
#else
    printf("Not debugging\n");
#endif
    printf("Running\n");
}

在用VC时,类向导会产生如下代码:

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

对于
#define new DEBUG_NEW
我们看下定义:

#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,并不会传入文件名与行号。
那么new操作符是在哪里类里面定义,并运行?我们知道MFC的类有很多,但是最重要的,最基础的类是CObject类,CObject类提供如下服务:
序列化支持,运行时类信息,动态创建,对象诊断输出。请注意,动态创建!我们看看CObject类的new操作符:

void *PASCAL operator new(size_t);
void *PASCAL operator new(size_t,void *p);
void *PASCAL operator new(size_t,LPCSTR lpszFileName,int nLine)
在第一个版本中:
void *PASCAL CObject::operator new(size_t nSize)
{
	#ifdef _AFX_NO_DEBUG_CRT
		return ::operator new(nSize);
	#else
	//调试
		return ::operator new(nSize, _AFX_CLIENT_BLOCK,NULL,0);
	//#endif
}

在实现文件中有#define new DEBUG_NEW那么CObject第二种形式的new操作符将被调用。这是文件名和new操作符所在的行号被写到额外分配的内存块中。注意,即使没有这行定义,调试版本下仍可以内存内存泄漏,只不过这是报告的信息中将没有更详细的提示。
请注意,在我们运行时,假设你出错了,双击调试窗口中的显示错误部分将会跳转到错误行,这就是这句代码的功能。