Release mode debugging with VC++

原创 2004年07月15日 00:22:00

The debug configuration of VC++ projects is the configuration that most debugging and development is done on. This is entirely appropriate because the debug information, lack of optimizations, and the extra debug checks in the Microsoft libraries, make stepping through your code and finding bugs much easier than in release builds.

However, sometimes you have to try and debug your release builds. Possible reasons include:

  • You may have a bug that only occurs in your release builds (for information on why this happens see this article) that you need to debug.
  • You may be trying to optimize your code, in which case stepping through the code and seeing what the compiler has created is essential.
  • Your shipped product may be crashing on a customer's machine.
You may be able to avoid release only crashes, and you may not need to optimize your release builds, but you never know when your program is going to start crashing on a distant customer's machine - and if you wait until it happens, it's too late.

If you want to be prepared and professional when your program crashes after you've released it then you need to create debug information for the version that you shipped, you need to archive the debug information, and you need to know how to use it.

At this point somebody inevitably says that it is obvious that enabling debug information is a nonsensical thing to do on a release build. They then claim that enabling debug information will make your program too big or too slow, and you certainly don't want to ship your precious program with symbols.

To this I say, the debug information in VC++ will not make your program bigger, it will not make it slower, and of course you don't ship your symbols. Done properly, enabling debug information lets you ship an executable that is less than a hundred bytes larger. The cost is essentially zero, and the benefits are huge. In fact, I claim that all executables and DLLs created with VC++ should be built with symbols - no exceptions. I further claim that failing to do this is irresponsible.

Enabling debug information in VC++ 6.0 is relatively easy - but terribly non-obvious. There are three separate settings that you have to change.

First go to Project->Settings, select the release build, then:

  • On the C/C++ tab for all librarys, DLLs and executables, in the general category, set Debug Info to Program Database. This tells the compiler to generate debug information.
  • On the link tab for all DLLs and executables, in the general category, put a check mark beside Generate Debug Info. This tells the linker to collate debug information into .pdb files. The linker also puts the name of the .pdb file in the executable, so the debugger can find it. That's why your executable gets a bit bigger. Dumpbin /headers will show you that information.
  • On the link tab, in the Project Options field, type in "/OPT:REF". This tells the linker to continue optimizing away unreferenced code. This is the default when debug information is turned off, but it defaults to off when you tell the linker to generate debug information. Failing to specify this will cause your executables and DLLs to get 10-20% larger. You should also specify /ignore:4089 to tell the linker to not generate warnings if it optimizes away all references to a DLL (this tip works with VC++ .Net also).
This MSDN article - - talks about the options for generating debug symbols, although it fails to differentiate between symbols that you ship with your product and symbols that you archive on site.

Creating debug information is nice, but it only helps if the debug information is available when you need it. In order to get maximum use out of the debug information, your build script (you do have an automated build script don't you?) should archive the .pdb file along with the executable (you do archive the executables you release don't you?), and you should put a label in your version control (you do use version control don't you?) so that you can recover the source code. Without these steps the debug information can easily be useless.

If you are using VC++ .Net or WinDbg and you are creating minidumps when your program crashes then the following steps are not necessary - just load the minidump. See this article for information on creating and using minidumps. However if you are using VC++ 6.0 or you aren't yet creating minidumps, follow these steps:

To analyze a crash address, load the .exe into DevStudio (yes, you can do that). Then instead of select Debug->Go, single step to load it into the debugger, and make sure the debug information loads - check the output window to see what it says. Then open the registers window, put an insertion point on EIP and type in the crash address.

When you hit enter, the debugger will take you to that address. Because you are in the debugger, the debugger will load the source code associated with that instruction, exactly as if you had crashed in the debugger.

Well, not exactly. The other registers aren't loaded, the stack isn't loaded, and a lot of information has been lost, but if it's an important bug and you're willing to pore over the stack dump for a while, you can frequently figure out what happened.

If you want to improve your odds, you should collect more information than just the instruction pointer. Check out John Robbins book "Debugging Applications" or download one of many exception handling articles - my favourite is here.

With all this information and a .pdb or .map file you can write tools to create call stacks - either starting from the EIP and working up the stack, or starting from a return address in WinMain and working down the stack. You can also programmatically load the stack and registers into the executable while it's in the debugger, to let the debugger give you more assistance in diagnosing the crash.

Let me know if you find this paper useful.

Please contact me if you have any questions.


VC++中Debug调试版本和Release发行版本的区别 引自: ...
  • 2013年04月05日 23:52
  • 1705

VC++ 6.0怎样生成发布(release)版本

1、确定Debug版无错,注意Trace等调试方法可能造成的错误 2、Release版的exe文件链接的是标准的MFC DLL,比如MFC42.dll。这些DLL在安装Windows的 时候,就会...
  • u011641865
  • u011641865
  • 2013年12月05日 23:55
  • 1254


from: Debug系列:VC++程序Release版崩溃的解决办法 VC++程序发布后,如果在客户那运行崩溃,且研发环境下无法本地...
  • eatjpg
  • eatjpg
  • 2015年09月22日 14:02
  • 326


vc中debug和release的不同 收藏  在使用VC开发软件的过程中,正当要享受那种兴奋的时候突然发现:release与debug运行结果不一致,甚至出错,而release又不方便调试,真的是...
  • hegeneral
  • hegeneral
  • 2016年04月27日 20:15
  • 2226


Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动。如果我们愿意,我们完全可以把Debug和Release的行为完全颠倒过来。当...
  • business122
  • business122
  • 2016年07月07日 17:27
  • 981


项目主页: 详细教程:
  • zhongguoren666
  • zhongguoren666
  • 2013年04月10日 10:29
  • 1646


在调试程序的时候经常遇到一个问题:debug版运行的很正常,查不出任何问题,到了release版,运行一会儿就崩溃了。最近一段时间查了很多资料,终于是找到了原因所在。讲解如下:     遇到这种问题...
  • oket007
  • oket007
  • 2013年12月23日 08:36
  • 879


大家都知道VC编译器默认生成debug版本的程序,但是debug版本程序无法运行在没有安装VC的电脑上, 这就要就我们生成release版本的程序,因为release版本在未安装VC的电脑上也能运行(...
  • rl529014
  • rl529014
  • 2016年04月21日 21:04
  • 1968

VC++如何调试程序的 Release 版本?(转)

如何调试程序的 Release 版本?(转) 很多时候程序的 Debug 版本运行没有任何问题,但是一旦发布 Release 版本后,运行就出错,着实让人郁闷。大家知道,VC++ 中 R...
  • u010025662
  • u010025662
  • 2016年12月07日 10:55
  • 98

在MFC中使用纯COM方式来操纵Flash OCX (IShockwaveFlash)

1. MFC中的控件(OCX)包装类 在VC++环境中,使用OCX会变得比较简单和快捷。 在Dialog中插入ActiveX,如:Shockwave Flash Object。 在建立了Dial...
  • sx5486510
  • sx5486510
  • 2014年05月21日 14:26
  • 2312
您举报文章:Release mode debugging with VC++