应用程序崩溃,没有解释

Col*_*nee 5 c++ crash

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

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

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

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

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

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

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

我们已经尝试使用windbg附加运行它(没有机会使用Visual Studio,开销太高),但是当崩溃发生时它没有报告任何内容.

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

Joh*_*ing 7

如果您的应用程序蒸发不生成转储文件,则可能是您的应用程序无法(或无法)处理的异常.这可能发生在两个实例中:

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

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

关于catch(...).这显然是邪恶的.应该(几乎)永远不会是catch(...)生产代码.catch(...)一般写作的人认为两件事之一:

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

-要么-

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

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

后者是一种高尚而强大的方法,但它的实施看起来要困难得多,而且它充满了危险.问题是您必须避免在异常处理程序中生成任何进一步的异常,并且您的计算机已处于非常不稳定的状态.通常非常安全的操作突然是手榴弹. new,delete任何CRT函数,字符串格式化,甚至基于堆栈的分配char buf[256]都很简单,可以让你的应用程序变得> POOF <并且不见了.你必须假设堆栈和堆都在废墟中.没有分配是安全的.

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