可预测的Windows中崩溃进程的退出代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可预测的Windows中崩溃进程的退出代码相关的知识,希望对你有一定的参考价值。

对于在Windows中正常退出的进程,进程的退出代码通常是main的返回值,或传递给std::exit的退出代码。然后可以使用%ERRORLEVEL%查询退出代码,并且可以用于确定程序是否正确执行,或者是否存在一些指示特定问题(特定于应用程序)的异常输入/失败。

但是,如果进程崩溃,我对退出代码感兴趣。举一个非常简单的示例程序:

int main()
{
    int * a = nullptr;
    *a = 0xBAD;
    return 0;
}

当我编译并在Windows中运行时,在命令行上我得到:

MyCrashProgram.exe -> crashes
echo %ERRORLEVEL%  -> -1073741819

退出代码始终为此数字。这引出了几个问题:

  • 基于无效的写入崩溃,退出代码-1073741819是否可以预测?
  • 如果是这样,有没有办法根据退出代码确定崩溃的类型?
  • 这是否随使用的编译器而改变(我使用的是MSVC 2012)?
  • 这是否随使用的Windows版本而改变(我使用的是Win10 TP)?
  • 这是否随体系结构而变化(例如x64 - 我使用的是Win32)?

注意,我对如何修改程序以捕获异常不感兴趣。我有兴趣对可能在现有程序中发生的崩溃进行分类,我可能无法对其进行修改。

答案

关于STATUS_ACCESS_VIOLATION的评论让我看到了关于GetExceptionCode的文档:

The return value identifies the type of exception. The following table identifies the exception codes that can occur due to common programming errors. These values are defined in WinBase.h and WinNT.h.

EXCEPTION_ACCESS_VIOLATION在下面的列表中映射到STATUS_ACCESS_VIOLATION。前缀为STATUS的列表中的所有异常都直接定义为以EXCEPTION为前缀的异常代码。在向RaiseException提供文档之后,它解释了在异常发生时尝试调试异常的过程,最后一步是:

If the process is not being debugged, or if the associated debugger does not handle the exception, the system provides default handling based on the exception type. For most exceptions, the default action is to call the ExitProcess function.

所以回答我的问题:

  • 是的,退出代码是可预测的,它映射到qazxsw poi。
  • 其他类型的错误将映射到其他常见的异常代码。但是,通过使用任意异常代码(未处理)调用RaiseException,进程的退出代码可以是任何内容
  • 退出代码取决于Windows SDK,而不是编译器,执行Windows版本或体系结构。虽然理论上这可以随着更新的Windows SDK而改变,但这对于向后兼容性来说是极不可能的。
另一答案

这是一个相关的EXCEPTION_STATUS_VIOLATION(强调我的):

流程退出代码没有标准。您可以将任何想要的内容传递给ExitProcess,这就是GetExitCodeProcess将返回的内容。内核没有解释这个值。如果你想要代码42意味着“发生了无限不可能的事情”那么你就会有更多的权力。

然而,有一个约定,退出代码为零意味着成功(虽然什么构成“成功”由程序作者自行决定)和非零退出代码意味着失败(再次,细节留给自行决定)程序员)。通常,退出代码的较高值表示更严重的故障类型。命令处理器ERRORLEVEL关键字的设计考虑了这些约定。

在某些情况下,您的进程将处于如此糟糕的状态,以至于组件将自行终止该进程。例如,如果进程无法找到它导入的DLL,或者其中一个DLL无法初始化,则加载程序将终止该进程并使用short blog post by Raymond Chen作为进程退出代码。我相信当程序因未处理的异常而崩溃时,异常代码将用作退出代码。

一位客户看到他们的程序崩溃,退出代码为3,无法弄清楚它的来源。他们从不在程序中使用退出代码。最终,识别出幻数3的来源:C运行时中止函数使用退出代码3终止进程。

另一答案

这绝不是一个全面的答案,而是一些提示,以便您可以继续前进。

我认为没有办法自动区分所有可能的崩溃原因。要做到这一点,您必须自己捕获错误并提供自己的退出代码

为了捕获所有可能的(可捕获的)错误,您必须设置异常和信号处理程序。这是因为访问冲突是Linux下的窗口和信号(SIGSEV)下的异常。

有关Windows上不同类型错误的详细信息,请参阅此问题:status code

这是Catching access violation exceptions的另一个主题

以上是关于可预测的Windows中崩溃进程的退出代码的主要内容,如果未能解决你的问题,请参考以下文章

跟踪 Windows 进程退出代码

怎么用c++编写一个Windows服务程序来监控另一个程序,崩溃后重新启动。

Android Studio Emulator崩溃:进程以退出代码139结束(由信号11中断:SIGSEGV)

scrapy主动退出爬虫的代码片段(python3)

怎么用c++编写一个Windows服务程序来监控另一个程序,崩溃后重新启动。

JVM:如何定义 java 可执行文件的退出代码?