【问题标题】:How can I debug a win32 process that unexpectedly terminates silently?如何调试意外以静默方式终止的 win32 进程?
【发布时间】:2010-09-27 13:29:06
【问题描述】:

我有一个用 C++ 编写的 Windows 应用程序,它偶尔会消失。我使用蒸发这个词是因为没有留下任何东西:没有来自 Windows 的“我们很抱歉”消息,没有来自 Dr. Watson 设施的崩溃转储......

有一次在调试器下发生崩溃,但调试器并没有中断——它显示应用程序仍在运行。当我手动暂停执行时,我发现我的进程不再有任何线程。

如何捕获此进程终止的原因?

【问题讨论】:

  • 你怎么知道应用程序没有正常退出?
  • 两个原因: 1. 应用程序在正常退出时,要经过几个循环才能正确关闭一些网络连接的硬件。崩溃后硬件仍在运行。 2.当应用程序正常退出时,调试会话结束。在这种情况下,它没有。
  • 您在问题中说应用程序线程已终止,然后主进程循环退出。这听起来像应用程序正常终止 - 并且“错误”可能是一个设计问题。检查您的线程循环以了解它们退出的原因(断点)。

标签: c++ debugging winapi crash


【解决方案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 标准库自动下载符号后,它也自动停止了导致问题的运行时异常。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-07-16
                    • 2014-06-13
                    • 1970-01-01
                    相关资源
                    最近更新 更多