应用程序崩溃,没有解释

时间:2011-03-07 19:21:05

标签: c++ crash

我想提前道歉,因为这不是一个很好的问题。

我有一个服务器应用程序,它在专用的Windows服务器上作为服务运行。非常随机,这个应用程序崩溃,并没有提示导致崩溃的原因。

当它崩溃时,事件日志有一个条目表明应用程序失败,但没有提供原因的线索。它还提供了有关故障模块的一些信息,但它似乎不太可靠,因为故障模块通常在每次崩溃时都不同。例如,最新的说它是ntdll,前一个说它是libmysql,之前的那个说它是netsomething,依此类推。

应用程序中的每个线程都包含在try/catch (...)中(从异常处理程序抛出的任何内容/未特别捕获),__try/__except(结构化异常)和try/catch(特定C ++)例外)。应用程序使用/ EHa编译,因此catch all也将捕获结构化异常。

所有这些异常处理程序都做同样的事情。首先,创建崩溃转储。其次,将一个条目记录到磁盘上的新文件中。第三,在应用程序日志中记录一个条目。在这些崩溃的情况下,没有发生这种情况。最底层的异常处理程序(try/catch (...))什么也不做,它只是终止线程。主应用程序线程处于睡眠状态,无法抛出异常。

应用程序日志文件只是停止记录。不久之后,监视服务器的进程注意到它不再响应,发送警报并再次启动它。如果服务器监视器注意到服务器仍在运行,但只是没有响应,则需要转储该进程并报告此情况,但这不会发生。

除了未捕获的异常之外,我可以提出的这种行为的唯一其他原因是对exit或类似的调用。搜索代码不会调用任何可以终止进程的函数。我还确保程序没有正常终止(即来自服务管理器的停止请求)。

我们尝试使用windbg连接运行它(没有机会使用Visual Studio,开销太高),但是在发生崩溃时它没有报告任何内容。

什么导致应用程序崩溃?我们开始没有选择,并认为它可能是硬件故障,但这对我来说似乎不太可能。

4 个答案:

答案 0 :(得分:7)

如果您的应用程序正在蒸发而不生成转储文件,那么很可能会生成您的应用程序无法(或无法)处理的异常。这可能发生在两个实例中:

1)生成顶级异常,并且该异常类型没有匹配的catch块。

2)您有一个匹配的catch块(例如catch(...)),但是您正在该处理程序中生成异常。当发生这种情况时,Windows将从您的程序中删除骨骼。您的应用程序将停止存在。不会生成任何转储,几乎不会记录任何内容,这是Windows为防止恶意程序拆除整个系统所做的最后努力。

关于catch(...)的说明。这显然是邪恶的。生产代码中应该(几乎)永远不会是catch(...)。撰写catch(...)的人通常认为有两件事之一:

“我的程序永远不会崩溃。如果发生任何事情,我想从异常中恢复并继续运行。这是一个服务器应用程序!ZOMG!”

-OR -

“我的程序可能会崩溃,但如果确实如此,我想在下来的路上创建一个转储文件。”

前者是一种天真和危险的态度,因为如果你试图处理并从每一个例外中恢复,你将会对你的操作足迹做一些坏事。也许你会咀嚼堆,保持应该关闭的资源,创造死锁或竞争条件,谁知道。你的程序最终将遭受致命的崩溃。但到那时调用堆栈与实际问题没有任何相似之处,并且没有转储文件可以帮助你。

后者是一个高贵的&强有力的方法,但它的实施似乎要困难得多,而且它充满了危险。问题是您必须避免在异常处理程序中生成任何进一步的异常,并且您的计算机已处于非常不稳定的状态。通常非常安全的操作突然是手榴弹。 newdelete,任何CRT函数,字符串格式,甚至像char buf[256]一样简单的基于堆栈的分配都可以使您的应用程序转到> POOF<然后走了你必须假设堆栈和堆都在废墟中。没有分配是安全的。

此外,还存在catch块无法捕获的异常,例如SEH异常。出于这个原因,我总是编写一个未处理的异常处理程序,并通过SetUnhandledExceptionFilter向Windows注册。在我的异常处理程序中,我在程序启动之前通过静态分配分配我需要的每个字节。在这个处理程序中做的最好(最强大)的事情是触发一个单独的应用程序启动,这将从你的应用程序外部生成一个MiniDump文件。但是,如果您非常小心,不能直接或间接调用任何CRT函数,则可以从处理程序本身生成MiniDump。基本上,如果它不是您正在调用的API函数,则可能不安全。

答案 1 :(得分:1)

我见过像这样的崩溃是由于内存损坏而发生的。您是否在像Purify这样的内存调试器下运行您的应用程序,看看是否能够解决潜在的问题区域?

答案 2 :(得分:1)

答案 3 :(得分:1)

这不是一个很好的答案,但希望它可以帮助你。

我曾经遇到过这些症状,在经历了一些痛苦的时间追逐原因之后,我发现了一个关于Windows的有趣的事情(来自MSDN):

  

取消引用可能无效   指针可以禁用堆栈扩展   在其他线程中。令人筋疲力尽的话题   堆栈扩展时的堆栈   被禁用,导致了   立即终止父母   进程,没有弹出错误窗口   或诊断信息。

事实证明,由于线程之间的一些错误设计的数据共享,我的一个线程最终会取消引用或多或少的随机指针 - 当然它有时会触及堆栈顶部的区域。追踪这些指针是很有趣的。

Raymond Chen的IsBadXxxPtr should really be called CrashProgramRandomly

中有一些技术背景
相关问题