如何调试仅在发布版本中发生的崩溃

时间:2013-08-28 08:57:22

标签: c++ windows visual-studio-2010 visual-studio debugging

我的一个程序中有一个奇怪的竞争条件导致它只在发布模式和OUTSIDE visual studio环境中崩溃。

如果我在Visual Studio中使用F5(发布或调试)在发布模式下启动此过程,它就可以正常工作。

如果我使用调试信息创建发布副本,它不会崩溃。

我想知道如何调试这样的问题..为什么它不会在视觉工作室内崩溃? Visual Studio是否会在启动它的发布版本时减慢可执行文件的速度?

3 个答案:

答案 0 :(得分:2)

问题实际上是如何在不改变导致崩溃的运行时行为的情况下调试应用程序。答案是更好的事后诊断

您可以改进异常处理代码,如果这是生产应用程序,则应该。

  1. 使用std::set_terminate

    安装自定义终止处理程序

    如果要在本地调试此问题,可以在终止处理程序中运行无限循环,并将一些文本输出到控制台以通知您已调用std::terminate。然后附加调试器并检查调用堆栈。

    在生产应用程序中,您可能希望将错误报告发送回家,最好与一个允许您分析问题的小内存转储一起发送。

  2. Microsoft具有结构化异常处理机制,允许您捕获硬件和软件异常。 See MSDN。您可以使用SEH保护代码的一部分,并使用与1)中相同的方法来调试问题。 SEH提供了有关从生产应用程序发送错误报告时可能使用的异常的更多信息。

  3. 如果它真的是一个竞争条件,那么正确的时间是至关重要的,我想,即使在发布模式下附加调试器也会改变行为,从而改变时间

答案 1 :(得分:1)

这回答“有什么不同”,但可能不完全解答为什么你的代码在发布模式下有竞争条件。

更改的一件事是当您移动到VS外部时,运行时正在使用哪个堆。据我所知,它甚至在发布模式下使用VS内部的调试堆。

由于必须锁定定义的堆分配,因此使用调试堆(在将内存填充到客户端代码之前填充内存,并在释放内存时再次填充内存)将更频繁地阻止竞争线程(导致更多顺序)执行),所以你可能会发现这是比赛发生的部分原因。

如果在调试环境中设置环境变量_NO_DEBUG_HEAP=1,(Configuration-> Debugging-> Environment Variables ...),那么你将在调试器中得到相同的东西。

不幸的是,调试这些事情可能非常棘手。我发现有用的一件事是为“我去过的地方”存储一个值数组(数组越简单,越好 - 所以整数值,或小字符串,或其他东西),而不是每次都打印一些东西。如果您可以在调试器中停止或以某种方式检测崩溃,则可以转储“跟踪”,并查看您如何到达现在的位置以及涉及的线程。

答案 2 :(得分:1)

Visual Studio中的F5与单独运行程序之间的主要区别在于,当程序最初在调试器下运行时,Windows在特殊的调试堆上运行程序。调试堆与普通堆不同,在某些情况下,这可能导致错误仅在普通堆上显示。

您可以运行该程序,然后附加调试器,然后它将使用普通堆,您的错误应该愉快地重现。为了防止程序在附加调试器之前“走得太远”,您可以在入口点内插入对Sleep()函数的调用。