只有在发布版本中程序崩溃,如何调试?

110
我这里遇到了类似于“薛定谔的猫”问题 -- 我的程序(实际上是测试套件,但仍然是一个程序)在发布模式下启动命令行时崩溃。通过类似于穴居人式的调试(即,在各个地方添加一些nasty printf()消息),我已经确定了导致代码崩溃的测试方法,但不幸的是,实际的崩溃似乎发生在某个析构函数中,因为我看到的最后一条跟踪消息是在其他执行良好的析构函数中。
当我尝试在Visual Studio内运行此程序时,它并没有崩溃。从WinDbg.exe启动也是一样的情况。只有从命令行启动时才会出现崩溃。顺便说一句,这在Windows Vista下发生,不幸的是我现在没有XP机器可以测试。
如果能让Windows打印出栈跟踪或者其他有意义的信息,而不是像正常退出程序一样终止程序,那就太好了。是否有人能给出任何建议,以便我能够在这里获取更多有意义的信息并修复此错误?
编辑:问题确实是由一个越界数组引起的,我在这篇文章中更详细地描述了它。感谢大家帮助找到这个问题!

你能提供那个测试方法的样例吗? - akalenuk
不好意思,这段代码太复杂了,很难在这里轻松粘贴。正如我之前提到的,问题并不是发生在测试方法本身,而是在析构函数之后。虽然在这个方法中没有未初始化的指针或其他类似的问题。 - Nik Reiman
3
大多数答案只是猜测。有一些常见的技巧可以在不连接调试器的情况下分析崩溃版本的构建:https://dev59.com/snVC5IYBdhLWcg3wykQt#18513077?stw=2 - Sebastian
也许这不是你的错:在g++中,优化级别-O3是否危险? - Brent Bradburn
29个回答

0

我发现这篇文章对你的情况很有用。我记得编译器选项有点过时了。请查看你的Visual Studio项目选项,看看如何为发布版本生成pdb文件等。


0

很奇怪的是,这种情况发生在调试器外而不是内部;在调试器中运行通常不会改变应用程序的行为。我会检查控制台和IDE之间的环境差异。此外,显然,编译时要关闭优化并启用调试信息,看看是否会影响行为。最后,检查其他人建议的事后调试工具,通常可以从中获得一些线索。


0

由于优化改变了代码行执行顺序,调试发布版本可能会很麻烦。这真的很令人困惑!

至少缩小问题范围的一种技术是使用MessageBox()来显示快速语句,说明你的代码已经到达程序的哪个部分(“Starting Foo()”,“Starting Foo2()”);将它们放在你怀疑的代码区域内函数的顶部(当它崩溃时你正在做什么?)。当你能够确定是哪个函数时,将消息框更改为代码块甚至是该函数中的单个行,直到将其缩小到几行。然后,您可以开始打印变量的值,以查看它们在崩溃点的状态。


他已经尝试过使用printf进行调试,所以消息框对于解决问题并没有什么新意。 - Greg Whitfield

0
尝试使用 _CrtCheckMemory() 查看分配的内存状态。 如果一切正常,_CrtCheckMemory 返回 TRUE,否则返回FALSE

0

您可以启用全局标志运行软件(在“Windows调试工具”中查找)。这通常可以帮助解决问题。


0
我也遇到了这个问题。在我的情况下,RELEASE模式在链接器定义中有msvscrtd.dll。我们将其删除后,问题得到解决。
另外,在链接器命令行参数中添加/NODEFAULTLIB也可以解决此问题。

0
我还要为未来的读者提供另一个可能性:检查一下你是在将日志记录到没有控制台窗口的应用程序的 stderr 还是 stdout 中(例如,你使用了 /SUBSYSTEM:WINDOWS)。这可能会导致崩溃。
我有一个 GUI 应用程序,在 debug 和 release 模式下都会将日志记录到 stderr 和文件中,因此始终启用日志记录。我在 debug 模式下创建了一个控制台窗口,以便轻松查看日志,但在 release 模式下没有创建。然而,如果 VS Debugger 附加到 release 构建上,它会自动将 stderr 管道到 VS 输出窗口。因此,只有在没有 Debugger 的 release 模式下,当我写入 stderr 时才会实际崩溃。
更糟糕的是,printf 调试显然不起作用,直到我追踪到根本原因(通过在不同位置插入无限循环,痛苦地对代码库进行二分)。

-3

我遇到了这个错误,即使尝试清理项目,VS也会崩溃。因此,我手动从发布目录中删除了obj文件,之后它就成功构建了。


-6

我同意Rolf的观点。因为可重复性非常重要,所以你不应该有一个非调试模式。所有的构建都应该是可调试的。拥有两个目标来进行调试会使你的调试负担增加一倍以上。只需发布“调试模式”版本,除非它无法使用。如果无法使用,则需要使其可用。


这可能适用于10%的应用程序,但肯定不适用于所有应用程序。你想玩以DEBUG版本发布的游戏吗?以易于反汇编的模式泄露你的商标秘密安全代码,甚至连PDB文件一起泄露?我猜不会。 - steffenj
Steffenj: 我希望游戏开发者能够找到漏洞。理想情况下,在他们发布之前,但如果是在发布之后,我希望他们能够获得足够的信息来重现和追踪它。如果这是秘密代码,商标不适用。PDBs?蛋白质数据库?Python调试器? - wnoise
我认为那是个不好的想法。可执行文件更大,它们没有被优化,运行速度也很慢。这些情况确实非常罕见,但当它们发生时尤其令人恼火。你不应该一直提供质量较差的产品,担心极为罕见的最坏案例调试。(我的回答并未被多数人反对。)我曾在NASA做过一些编程工作;我们说每一行代码至少应该测试一次。单元测试也可以帮助。 - CodeLurker

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