Debug和Release模式到底有什么区别
2009-11-30 08:33

有些人可能会问VC中的Debug和Release模式到底有什么区别,能不能将两者混用。

这里是常见的看法:http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/775ce067-b225-4141-8b86-2d7e9b61db97/ 

syperk说:"As a result, I've switched to compiling my debug builds using the /MD switch. If you do this, you also have to undefine the _DEBUG preprocessor macro. Otherwise you get lots of errors about _CrtDebugReportW() not found. This function is apparently inserted into your code if _DEBUG is defined, but is only defined in the debug CRT. As long as optimization is off it seems to be perfectly possible to debug programs compiled this way, and there are no concerns about CRT incompatibility.".

但是他的说法并不完全正确。混用有很多问题。其中,最重要的一点是,混用通过不同的编译参数生成的模块是非常糟糕的做法,特别是涉及到条件编译的时候。

实际上,"Debug"和"Release"只是两套IDE预先设定好的编译参数和宏定义组合(例如我们经常遇到的_DEBUG和NDEBUG宏)。编译器并不知道Debug和Release之分(不过MD和MDd编译参数会区分Debug版本和Release版本的运行时库)。当混用用Debug设置编译的程序和Release版本的运行时库的时候,由于它们生成的时候使用的是两套不同的编译选项,因此非常可能互不兼容。

比如,如果你在你的Debug配置中将"MDd"改为"MD"(链接到Release版本的运行时库),然后编译下面的代码 (不要去掉配置中的_DEBUG宏定义,否则Debug编译模式就不再是Debug了(/MDd会隐式的定义这个宏,而IDE会显式的在配置中定义它)):

#include <iostream>
#include <string>
using namespace std;
int main()
{
    std::string str;
    return 0;
}

 

你会说,这个程序工作的好好的啊。如果你进一步的查看生成的exe文件,你会发现它实际上引用了两个dll,一个是msvcp90d.dll,另一个是msvcr90.dll。你混用了Debug版本和Release版本的运行时库。这同时掩盖了潜在的不兼容!

关键在这里(use_ansi.h):

#ifdef _DEBUG
#pragma comment(lib,"msvcprtd")
#else /* _DEBUG */
#pragma comment(lib,"msvcprt")
#endif /* _DEBUG */

 

如果你禁用了这里的自动链接,并手动链接到msvcp90.dll,你将得到“unresolved symbol”的错误。这是因为在Debug模式和Release模式下,string类的实现是不同的。这是一个很好的不兼容的例子。

error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(struct std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Has_debug_it)" (__imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@U_Has_debug_it@01@@Z) referenced in function _main

幸运的是,这仅仅是一个链接时错误。否则你将不得不花费大量的时间在运行期找出这些很隐蔽的不兼容问题。

VC9中的STL实现花费了不少精力避免上述的问题。因此你可以在你的程序中禁用"_HAS_ITERATOR_DEBUGGING"宏,并同时和运行时库保持兼容(运行时库编译的时候这个宏是定义的)。但前提是你的程序必须和运行时库使用一致的Debug或者Relese模式。因此不要混用Debug和Release模式。最好是能够保证各个模块使用完全一致的编译参数进行编译。这样你就不必为潜在的不兼容问题烦恼了。


posted on 2010-08-15 23:24  kangwang1988  阅读(7046)  评论(0编辑  收藏  举报