Visual C++:在Release模式下启动/不启动调试的区别

17
启动调试(F5无调试启动(CTRL-F5发布模式下编译代码时有什么区别?
对于某些C++代码,我发现CTRL-F5F5快10倍。如果我没有错的话,对于F5,调试器会附加到正在执行的进程中,并且对于CTRL-F5,则不会这样做。由于这是发布模式,所以编译后的代码没有任何调试信息。因此,如果我没有任何断点,那么两者的执行时间应该是相同的,不是吗?!
(假设Release和Debug模式是创建新Visual C++项目时的典型配置。)
4个回答

18

问题在于,如果Windows检测到您的程序正在运行调试器,则会使用特殊的Debug Heap。这似乎是在操作系统层面上发生的,与编译的任何Debug/Release模式设置无关。

您可以通过设置环境变量来解决此“功能”:_NO_DEBUG_HEAP=1

同样的问题一直困扰着我; 今天我找到了以下内容,本帖由此派生: http://blogs.msdn.com/b/larryosterman/archive/2008/09/03/anatomy-of-a-heisenbug.aspx


我正在使用C#编程,遇到了同样的问题。我通过在项目属性 > 调试 > 命令行参数中添加“-hd”命令行选项来解决了这个问题。谢谢! - Daniel Bonetti

10

"启动不带调试" 只是告诉 Windows 以通常方式运行应用程序。

"启动并调试" 启动 VS 调试器并让它在调试器内运行应用程序。

这与调试/发布构建设置没有太大关系。

当你构建应用程序的默认“调试”配置时,与发布构建相比,将有以下主要区别:

  • 生成的代码不会被优化,因此更接近于源代码,更容易进行调试。
  • 编译器和链接器将输出一个包含大量额外信息的 .PDB 文件,以帮助调试器——该信息的存在或缺失对代码的性能没有影响,只影响调试的便利性。
  • 条件宏(如 ASSERT 和 VERIFY)在发布版本中将成为无操作(no-op),但在调试版本中处于活动状态。

每个条目都是独立且可选的!您可以打开或关闭其中任何一个或多个,并仍然在调试器下运行代码,只是会更困难一些。

当您使用“调试”运行时,由于几个原因,事情会有所不同:

  • VS 调试器在启动时非常低效,部分原因是因为 VS 中的所有东西都很慢——在 VS2010 之前的版本中,IDE 进入调试模式时屏幕上的每个像素约会重新绘制 30 次,会有很多闪烁和闪烁。
  • 根据配置方式,调试器可能会花费大量时间启动,尝试为您的进程中的许多操作系统组件加载符号(即 PDB 文件)——它可能会尝试从网络获取这些文件,在某些情况下可能需要很长时间。
  • 你的应用程序通常执行的一些活动(如加载 DLL、启动线程、处理异常)都会引起调试器的警报。这会降低它们的速度,并使它们倾向于顺序运行。

Will:对于发布模式,如果没有断点,那么代码不应该在调试器中以全速执行吗?如果没有调试信息和断点,调试器对代码的“操作”究竟会导致什么减速呢? - Ashwin Nanjappa
Ashwin:我在我的回答的第二部分尝试回答了这个问题。调试器会在代码的许多正常活动中被调用,这会导致延迟和通常的并行性损失。此外,它可能刚开始时已经清空了系统中的所有缓存,这意味着您的应用程序启动会更慢。 - Will Dean
2
Ashwin:这是您的应用程序在调试器下运行时会表现出不同行为的事项清单:http://msdn.microsoft.com/en-us/library/ms679302%28VS.85%29.aspx - Will Dean

4
"

IsDebuggerPresent()OutputDebugString()的行为取决于是否连接了调试器。

IsDebuggerPresent()只是返回另一个值,因此您的程序可以根据此值做出反应并有意识地表现得不同。如果没有连接调试器,OutputDebugString()将更快地返回,因此如果它被调用多次,则会发现程序在没有调试器的情况下运行得更快。"


0
当运行“调试模式”时,即使在发布模式下也会使用调试堆。这会导致使用大量malloc/free或new/delete的代码严重减速,在C++代码中可能会发生这种情况,因为库/类倾向于隐藏这些内存管理细节。

1
从未见过这样的情况。当进行发布构建时,它会链接到非调试 CRT,因此不可能出现调试堆的情况。 - sharptooth
@sharptooth:这里有两个层面在起作用。一个是CRT,另一个是Windows本身,它也可能决定在调试堆上运行任何进程。这篇博客文章比我更好地解释了它:http://preshing.com/20110717/the-windows-heap-is-slow-when-launched-from-the-debugger/ - Cygon
@Cygon:是的,但操作系统级别通常处理来自运行时堆内部的大型分配,并且运行时堆本身可能会增加很多额外开销,这会使得操作系统级别的调试工具往往很难忽略。 - sharptooth
这个答案是正确的,但没有比之前的回答更多的内容,并且没有提供解决方案。请查看提到_NO_DEBUG_HEAP的答案。 - Bruce Dawson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接