调试和解决非常零星的崩溃的想法 - 似乎是一个AV

时间:2009-09-19 19:30:13

标签: c++ exception-handling crash c++builder access-violation

我有一个错误导致我的应用程序消失而没有错误消息或类似的东西。该应用程序刚刚从屏幕上消失,它不再列在任务管理器上。

该应用程序是一个C ++ Builder应用程序(CBuilder2007),我已经尝试了所有我想到的尝试捕获此错误。它很少发生,它从未在我的机器上崩溃,只在我们在办公室的测试机器中崩溃过一次。对于我们的一个客户来说,它更频繁地发生,但我们还没有找到实现它的方法,或者找到发生这种情况的情况。这是一个沉重的多线程应用程序。

我在这个应用程序中启用了madExcept,但它没有抓到任何东西。我已经使用set_terminateset_unexpected RTL例程添加了处理程序,没有任何运气。

我所拥有的唯一信息来自我所做的“加载器应用程序”包装器,以从主应用程序获取返回代码。它以C0000005代码退出,我相信这意味着发生了访问冲突。奇怪的是,如上所述,甚至没有Windows错误框或类似的东西。

问题是:有任何想法试图抓住这个吗?因为我甚至不知道这可能发生的事情(我在应用程序周围有很多日志记录,但应用程序崩溃之前的“踪迹”并没有导致任何地方)我的想法set_terminateset_unexpected例程是为了获得一个堆栈跟踪来试图查看错误的生成位置,但到目前为止这些例程根本没有被调用(至少在我的办公室里发生这种情况的唯一时间)< / p>

提前致谢


[Update 22.Sept.2009]使用AddVectoredHandlerException我能够从崩溃中获得一个callstack,现在我可以开始尝试隔离并修复bug。感谢!!!

11 个答案:

答案 0 :(得分:6)

terminate / unexpected仅由C ++运行时调用,仅用于C ++异常。

访问冲突是一个SEH例外 - 要注意这一点,您需要SetUnhandledExceptionFilterAddVectoredExceptionHandler(如果它是&gt; = XP)。然后,您可以使用MiniDumpWriteDump和相关的。

创建一个小型转储

答案 1 :(得分:3)

我偶然遇到过这样的问题,应用程序似乎停止了。不会调用异常处理程序或崩溃处理程序等。该应用程序似乎只是立即终止。

不幸的是,我无法就如何弄清楚提供任何简单的建议。这里的其他回复有一些好主意。如果根据PiotrLegnica的回应,你还没有抓住未处理的异常,那么你应该这样做。

但是,如果程序真的像我看到的那样立即终止,那么即使是在SetUnhandledExceptionFilter注册的处理程序也无济于事。该程序在调用处理程序之前停止所有执行和内存不足。

尽管如此,我还是想到了一些想法:

  • 检查您的代码库是否有TerminateProcessTerminateThread的使用情况。我可能错了,但我相信使用这些可能会导致你看到的症状。
  • 检查函数指针的任何用法,包括传递给Window API的回调和WindowProc。确保调用约定,参数列表和返回值都正确匹配。如果正在编译函数指针以使代码编译,则可能隐藏了可能导致不良事件发生的不匹配。
  • 考虑您正在使用的任何第三方库或组件(ActiveX等)。也许他们在自己的代码中有一个错误导致这个问题在不明显的情况下。您可以尝试在调用其函数之前和之后放置日志记录语句,以查看是否可以确定程序停止的位置。
  • 如果没有其他帮助,请在您自己的代码中添加更多日志记录。

关于日志记录的主题:当我不得不帮助追踪这样的问题时,我们最终创建了一个日志记录机制,每次程序启动时都会创建一个唯一命名的日志,如果该计划正常结束。这样,每次发生终止问题时,都会留下另一个日志文件。我们使用日期时间戳作为唯一命名方面的一部分。日志的内容只是记录程序中发生的操作。我们经历了几次迭代检查日志,然后添加了更多的日志记录语句,直到最终导致我们来源。在追踪问题的同时,这种机制让我们对问题的发生频率有了清晰的认识。你可能会考虑类似的事情。

答案 2 :(得分:1)

我之前看到过这种情况发生在C ++代码上两次:

  1. 使用LoadLibraryGetProcAddress动态加载Windows API,然后通过使用错误的调用约定声明的函数指针调用它(它应该有__stdcall但是没有“T)。

  2. 当一个类有一个函数指针作为成员变量,并且在初始化之前调用了函数指针。

答案 3 :(得分:1)

您必须在调试模式下运行应用程序,并通过越来越多地运行复杂场景集来进行压力测试,这样您就可以在调试模式下捕获异常。

同样尝试再次查看包含访问线程之间共享内存的代码,可能是多线程的问题,你可以尝试在每个共享内存访问上设置锁定以确保多线程处理(但这会降低性能) )

答案 4 :(得分:1)

Re:应用程序消失,客户机器是否在Windows中关闭了“报告错误”设置?它隐藏在“系统”控制面板中,当它关闭时,正常的Windows崩溃通知对话框被压制。

答案 5 :(得分:1)

也许添加一个好的,老式的信号处理程序可能至少可以说明发生了什么?

答案 6 :(得分:1)

如果您无法在本地重现,那么您将遇到困难。 正如其他人所建议的那样,捕获崩溃转储或使用调试器捕获程序当然是最佳选择。

如果这是我的问题,我会尝试使用sysinternals中的Process Monitor进行监控。将其设置为仅监视您的进程,如果需要很长时间,请确保它由文件支持。这可能会告诉您哪个线程处于活动状态以及进程结束时发生了什么。您也可以尝试为Windows找到相应的“truss” - 一个监控系统调用的程序。

答案 7 :(得分:0)

我可能会考虑过去做的另外两件事:堆栈溢出(无限递归,导致大型临时变量位于堆栈上的错误参数等),或者辅助中未处理的异常线程。

答案 8 :(得分:0)

配置您的应用以在发生崩溃时编写小型转储。

我不确定这在CBuilder中是怎么回事,但在visual studio中你可以直接加载这个转储,它会显示一个完整的callstack和导致崩溃的源代码行。

我经常使用它来查找客户机器上发生崩溃的原因 但是,特别是对于多线程应用程序而言,真正的错误(例如内存早期发布)很可能在实际崩溃之前发生了一段时间,因此找到根本原因可能仍然非常困难。

答案 9 :(得分:0)

订阅Windows错误报告。有些客户可能会向微软公司报告AV,他们很乐意与您分享收集的堆栈跟踪信息。作为一个好处,您可以获得有关应用程序可靠性的详细数据。管理层喜欢这些。例如。您可以设定“到2010年将错误频率降低50%”的目标。

答案 10 :(得分:0)

让您的应用程序运行,然后附加windbg(崩溃模式),即第一次出现第二次机会异常生成转储。记得放上符号文件(PDB)。