2013-08-28 128 views
3

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

如果我使用F5(无论是发行版还是调试版)在Visual Studio中以发布模式启动此过程,它就会起作用。

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

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

+3

听起来像在某些时候,你正在调用未定义的行为 – nijansen

+0

我甚至不知道这个问题,因为我无法调试它,并且应用程序的代码太大而无法在此处发布 –

+0

当您调用UB时,可能会发生,包括你观察到的。有无数的方法来调用UB,其中没有人会愿意在这里开始列出它们。 – PlasmaHH

回答

2

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

你可以改进你的异常处理代码,如果这是一个生产应用程序,你应该。

  1. 安装使用std::set_terminate

    如果你想在本地调试这个问题自定义终止处理程序,您可以运行终止处理和输出一些文本内的无限循环到控制台,通知您std::terminate有被称为。然后附加调试器并检查调用堆栈。

    在生产应用程序中,您可能希望将错误报告发送回家,理想情况下还有一个允许您分析问题的小内存转储。

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

如果它确实是一个竞争条件,然后在正确的时间是至关重要的,我想,在安装调试器,即使在发行模式不改变的行为,因此定时

1

这回答“有什么不同”,但可能不是您的代码在发布模式中存在争用条件的完整答案。

当你移动到VS之外的版本时,有一件事就是运行时正在使用堆。就我所知,它甚至在释放模式下也使用VS中的调试堆。

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

如果您在调试环境(配置 - >调试 - >环境变量...)中设置环境变量_NO_DEBUG_HEAP=1,那么您将在调试器中得到相同的结果。

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

1

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

你可以运行程序,然后附加调试器,然后它会使用普通的堆,你的bug应该愉快地重现。为防止程序在连接调试器之前“过度”,您可以在入口点内插入一个调用函数Sleep()函数。

相关问题