如何调试意外以静默方式终止的 win32 进程?
Posted
技术标签:
【中文标题】如何调试意外以静默方式终止的 win32 进程?【英文标题】:How can I debug a win32 process that unexpectedly terminates silently? 【发布时间】:2010-09-27 13:29:06 【问题描述】:我有一个用 C++ 编写的 Windows 应用程序,它偶尔会消失。我使用蒸发这个词是因为没有留下任何东西:没有来自 Windows 的“我们很抱歉”消息,没有来自 Dr. Watson 设施的崩溃转储......
有一次在调试器下发生崩溃,但调试器并没有中断——它显示应用程序仍在运行。当我手动暂停执行时,我发现我的进程不再有任何线程。
如何捕获此进程终止的原因?
【问题讨论】:
你怎么知道应用程序没有正常退出? 两个原因: 1. 应用程序在正常退出时,要经过几个循环才能正确关闭一些网络连接的硬件。崩溃后硬件仍在运行。 2.当应用程序正常退出时,调试会话结束。在这种情况下,它没有。 您在问题中说应用程序线程已终止,然后主进程循环退出。这听起来像应用程序正常终止 - 并且“错误”可能是一个设计问题。检查您的线程循环以了解它们退出的原因(断点)。 【参考方案1】:您可以尝试使用 windows debugging tool package 中的 adplus 实用程序。
adplus -crash -p yourprocessid
自动转储工具为异常提供小型转储,并在应用程序崩溃时提供完整转储。
【讨论】:
【参考方案2】:如果您使用的是 Visual Studio 2003 或更高版本,您应该启用调试器“第一次机会异常”处理程序功能,方法是打开“调试菜单 | 下的所有调试异常中断”选项。例外对话框。在调试器中启动进程的调试构建之前打开每个选项。
默认情况下,调试器中的大多数 First Chance Exception 处理程序都已关闭,因此如果 Windows 或您的代码抛出异常,调试器希望您的应用程序处理它。
First Chance Exception 系统允许调试器拦截进程和/或系统抛出的每一个可能的异常。
http://support.microsoft.com/kb/105675
【讨论】:
【参考方案3】:发布的所有其他想法都很好。
但听起来应用程序正在调用 abort() 或 terminate()。
如果你在调试器中运行它,在这两个方法和 exit() 上都设置一个断点,只是为了更好的衡量。
这里列出了可能导致terminate to be called because of exceptions 出错的情况。
另请参阅: Why destructor is not called on exception?
这表明如果没有捕获到异常,应用程序将终止()。因此,在 main() 中添加一个 catch 块来报告错误(到日志文件),然后重新抛出。
int main()
try
// Do your code here.
catch(...)
// Log Error;
throw; // re-throw the error for the de-bugger.
【讨论】:
您可能希望将 Kernel32!TerminateProcess() 和 kernel32!ExitProcess() 添加到断点集。此外,DLL 的 DLL_PROCESS_DETACH 消息上的断点对 DllMain() 可能会有所帮助。这些函数的面向线程版本的断点也可能提供线索。【参考方案4】:好吧,问题是您遇到了访问冲突。您可能希望附加 WinDBG 并打开所有异常过滤器。它可能仍然无济于事 - 我的猜测是您遇到了没有引发异常的内存损坏。
你可能想看看enabling full pageheap checking
您可能还想查看这个关于堆损坏的older question,了解有关工具的一些想法。
【讨论】:
【参考方案5】:这种突然消失的最常见原因是堆栈溢出,通常是由某种无限递归引起的(当然,这可能涉及一系列相互调用的多个函数)。
在你的应用中有这种可能性吗?
【讨论】:
这让我想起了关于堆栈溢出意味着什么的问题,当应用程序报告堆栈溢出时。现在当应用程序不报告堆栈溢出时会发生什么,原因是堆栈溢出。多么幸运,这个网站上的所有问题都被stack o解释了【参考方案6】:您可以在 Windows 上查看 Event Viewer 中的 Windows 日志。
【讨论】:
【参考方案7】:首先我想说的是,我在 Windows 开发方面的经验并不多。 在那之后,我认为这是一个典型的案例,日志可能会有所帮助。
通常调试和记录提供正交信息。如果您的调试器没用,那么日志可能会对您有所帮助。
【讨论】:
【参考方案8】:这可能是对 _exit() 或某些 Windows 等效项的调用。尝试在 _exit 上设置断点...
【讨论】:
【参考方案9】:您是否尝试过 PC Lint 等并在您的代码上运行它? 尝试使用最大警告进行编译 如果这是一个 .NET 应用程序 - 使用 FX Cop。
【讨论】:
【参考方案10】:想到可能的原因。
TerminateProcess() 堆栈溢出异常 处理异常时出现异常最后一个特别会导致应用程序立即失败。 堆栈溢出 - 您可能会收到通知,但不太可能。
进入调试器,将所有异常通知更改为“始终停止”而不是“如果未处理则停止”,然后执行导致程序失败的操作。如果您遇到异常,调试器将停止,您可以确定这是否是您要查找的异常。
【讨论】:
【参考方案11】:我花了几个小时试图在 Windows 7 上运行 64 位应用程序的 Visual Studio 2017 上对此进行深入研究。我最终不得不在 RtlReportSilentProcessExit 函数上设置断点,该函数位于ntdll.dll 文件。只需基本函数名称即可让 Visual Studio 找到它。
也就是说,在我让 Visual Studio 为 C 标准库自动下载符号后,它也自动停止了导致问题的运行时异常。
【讨论】:
以上是关于如何调试意外以静默方式终止的 win32 进程?的主要内容,如果未能解决你的问题,请参考以下文章
mongodb启动服务时候报错。错误1067,进程意外终止。
Visual Studio 2017 调试器的工作进程(msvsmon.exe)意外退出 调试将终止