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

时间:2015-05-28 16:08:45

标签: c++ windows crash exit-code

对于在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)?

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

3 个答案:

答案 0 :(得分:4)

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

返回值标识异常的类型。下表列出了由于常见编程错误而可能发生的异常代码。这些值在WinBase.h和WinNT.h中定义。

EXCEPTION_ACCESS_VIOLATION映射到后面列表中的STATUS_ACCESS_VIOLATION。前缀为STATUS的列表中的所有异常都直接定义为前缀为EXCEPTION的异常代码。根据{{​​3}}的文档,它解释了在异常发生时尝试调试异常的过程,最后一步是:

如果未调试进程,或者关联的调试器未处理异常,则系统会根据异常类型提供缺省处理。对于大多数例外,默认操作是调用ExitProcess函数。

所以回答我的问题:

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

答案 1 :(得分:2)

这是一个相关的short blog post by Raymond Chen(强调我的):

  

流程退出代码没有标准。你可以通过任何你   想要ExitProcess,那就是GetExitCodeProcess会给出的   背部。内核没有解释这个值。如果你想要的话   代码42表示“发生了无限不可能的事情”   给你更大的力量。

     

然而,有一个约定,退出代码为零意味着   成功(虽然构成“成功”的是由自由裁量权决定的   该程序的作者)和非零退出代码意味着失败   (再次,详细信息由程序员自行决定)。经常,   退出代码的较高值表示更严重的故障类型。   命令处理器ERRORLEVEL关键字是用这些设计的   惯例。

     

在某些情况下,您的流程会处于如此糟糕的状态   组件将自行终止该过程。对于   例如,如果进程无法找到它导入的DLL,或者一个   这些DLL无法初始化,加载器将终止   处理并使用status code 作为流程退出代码。 我相信   当程序因未处理的异常而崩溃时,   异常代码用作退出代码。

     

客户看到他们的程序崩溃,退出代码为3和   无法弄清楚它来自哪里。他们从不使用那个出口   代码在他们的程序中。最终,幻数3的来源   已确定: C运行时中止函数终止进程   退出代码3

答案 2 :(得分:0)

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

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

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

有关Windows上不同类型错误的详细信息,请参阅此问题: Catching access violation exceptions

这是signal handling on linux

的另一个主题