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

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个回答

3
为了获得可以分析的崩溃转储:
  1. 为您的代码生成pdb文件。
  2. 重新定位以使您的exe和dll加载到相同的地址。
  3. 启用post mortem调试器,如Dr. Watson
  4. 使用诸如crash finder之类的工具检查崩溃失败地址。

您还应该查看Windows调试工具中的工具。 您可以监视应用程序并查看在第二次机会异常之前的所有一次性异常。

希望对您有所帮助...


2

我曾经遇到过一个问题,当时我的应用程序表现得与你的类似。后来发现是sprintf中的一个严重缓冲区溢出。当然,在调试器附加的情况下它可以正常工作。我所做的就是安装了一个未处理异常过滤器(SetUnhandledExceptionFilter),其中我只是无限地阻塞(使用等待单个对象函数WaitForSingleObject,等待一个虚假的句柄,并将超时值设置为INFINITE)。 所以你可以按照以下方式进行操作:
long __stdcall MyFilter(EXCEPTION_POINTERS *)
{
    HANDLE hEvt=::CreateEventW(0,1,0,0);
    if(hEvt)
    {
        if(WAIT_FAILED==::WaitForSingleObject(hEvt, INFINITE))
        {
            //log failure
        }
    }
} // 在wmain/WinMain中的某个地方: SetUnhandledExceptionFilter(MyFilter);
之后,在错误已经显现出来后再附加调试器(gui程序停止响应)。 然后,您可以立即拍摄转储文件并进行调试:
.dump /ma path_to_dump_file
或者直接调试。最简单的方法是跟踪运行时异常处理机制保存处理器上下文的位置:
s-d esp Range 1003f
该命令将搜索堆栈地址空间中的CONTEXT记录(提供搜索长度)。我通常使用类似于'l?10000'的东西。请注意,不要使用过大的数字,因为您需要的记录通常靠近未处理的异常过滤器帧。 1003f是用于捕获处理器状态的标志组合(我认为它对应于CONTEXT_FULL)。 您的搜索将类似于下面这样:
0:000> s-d esp l1000 1003f
0012c160 0001003f 00000000 00000000 00000000 ?...............
一旦你得到了结果,就可以在cxr命令中使用地址:
.cxr 0012c160
这将带您进入这个新的CONTEXT,正好在崩溃时(您将在应用程序崩溃时得到完全的堆栈跟踪)。 此外,使用以下命令:
.exr -1
以确定发生了哪个异常。 希望能有所帮助。

1
根据我的经验,最常见的问题是内存损坏问题。
例如:
char a[8];
memset(&a[0], 0, 16);

: /*use array a doing some thing */

在调试模式下运行代码很可能是正常的。

但是在发布模式下,可能会导致崩溃。

对我来说,查找越界内存位置太费力了。

使用一些工具,比如Visual Leak Detector(Windows)或valgrind(Linux)是更明智的选择。


1

Vista SP1实际上在系统中内置了一个非常不错的崩溃转储生成器。但不幸的是,默认情况下它没有被启用!

请参阅本文:http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

这种方法的好处是,受影响的系统无需安装任何额外的软件。让你来狠狠地撕裂吧,老兄!


1
关于您在获取诊断信息方面遇到的问题,您是否尝试过使用adplus.vbs作为WinDbg.exe的替代品?要附加到正在运行的进程,请使用
adplus.vbs -crash -p <process_id>

或者在崩溃发生时快速启动应用程序:

adplus.vbs -crash -sc your_app.exe

有关adplus.vbs的完整信息可以在此处找到:http://support.microsoft.com/kb/286350


1

已连接调试器的 Ntdll.dll

从IDE或WinDbg启动程序与从命令行/桌面启动程序有一个鲜为人知的区别,就是在使用调试器(即IDE或WinDbg)附加时,ntdll.dll 使用了不同的堆实现,对内存分配/释放执行了一些小的验证。

您可以在 ntdll.dll 中出现意外用户断点 中阅读一些相关信息。一个可能能够帮助您识别问题的工具是 PageHeap.exe

崩溃分析

您没有说明您遇到的“崩溃”是什么。当程序崩溃并提示您向 Microsoft 发送错误信息时,您应该能够单击技术信息并检查至少异常代码,并且通过一些努力,甚至可以进行死后分析(请参见Heisenbug:WinApi程序在某些计算机上崩溃)中的说明)。


1
我看到了很多正确的答案,但是没有一个对我有帮助。在我的情况下,SSE指令未对齐内存的使用是错误的。查看你的数学库(如果你使用的话),尝试禁用SIMD支持,重新编译并重现崩溃。
例如:一个项目包括mathfu,并使用带有STL向量的类:std::vector< mathfu::vec2 >。这种用法可能会在mathfu::vec2项的构建时导致崩溃,因为STL默认分配器不保证所需的16字节对齐。在这种情况下,可以在每个mathfu的include之前定义#define MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT 1,以Release配置重新编译并再次检查。 DebugRelWithDebInfo 配置对我的项目很有效,但是 Release 配置却不行。这种行为背后的原因可能是调试器进程分配/释放请求并进行一些内存簿记以检查和验证对内存的访问。 我在 Visual Studio 2015 和 2017 环境中遇到了这种情况。

0

这里有一个案例,可能会对某些人有所启示。在Qt Creator中,它只在发布版本中崩溃,而不是在调试版本中。我正在使用.ini文件(因为我更喜欢可以复制到其他驱动器的应用程序,而不是那些如果注册表损坏就会丢失其设置的应用程序)。这适用于将其设置存储在应用程序目录树下的任何应用程序。如果调试和发布构建位于不同的目录下,则它们之间可能存在不同的设置。我在其中一个中选中了首选项,而在另一个中没有选中。结果发现这是我的崩溃源。很高兴我找到了它。

我不想说,但我只能在MS Visual Studio Community Edition中诊断出崩溃;在安装了VS之后,在Qt Creator中让我的应用程序崩溃,并选择在Visual Studio的调试器中打开它。虽然我的Qt应用程序没有符号信息,但事实证明Qt库有一些符号信息。这使我找到了问题所在的行,因为我可以看到正在调用哪个方法。(尽管如此,我认为Qt是一个方便、强大且跨平台的LGPL框架。)


0

让你的程序在异常发生时生成小型转储文件(mini dump),然后在调试器中打开它(例如,WinDbg)。需要关注的主要函数:MiniDumpWriteDump、SetUnhandledExceptionFilter。


0

我曾经遇到过类似的问题,是在使用GCC时发生的。后来发现这是因为在开发过程中没有启用某些过于激进的优化,只有在最终发布时才启用了。

说实话,这是我的错,而不是GCC的错,因为我没有注意到我的代码依赖于特定的优化未被执行。

我花了很长时间才找到问题所在,最终是通过在新闻组上询问并得到他人的帮助才解决的。所以,如果你也遇到了类似的问题,让我回报一下恩情吧。


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