对于在Windows中正常退出的进程,进程的退出代码通常是main
的返回值,或传递给std::exit
的退出代码。然后可以使用%ERRORLEVEL%
来查询退出代码,这可用于确定程序是否正确执行,或者是否存在一些指示特定问题(特定于应用程序)的异常输入/失败。
但是,如果进程崩溃,我对退出代码感兴趣。举一个非常简单的示例程序:
int main()
{
int * a = nullptr;
*a = 0xBAD;
return 0;
}
当我编译并在Windows中运行时,在命令行上我得到:
MyCrashProgram.exe -> crashes
echo %ERRORLEVEL% -> -1073741819
退出代码始终为此数字。这引出了几个问题:
-1073741819
是否可以预测? 注意,我对如何修改程序以捕获异常不感兴趣。我有兴趣对可能在现有程序中发生的崩溃进行分类,我可能无法对其进行修改。
答案 0 :(得分:4)
关于STATUS_ACCESS_VIOLATION
的评论让我看到GetExceptionCode
上的文档:
返回值标识异常的类型。下表列出了由于常见编程错误而可能发生的异常代码。这些值在WinBase.h和WinNT.h中定义。
EXCEPTION_ACCESS_VIOLATION
映射到后面列表中的STATUS_ACCESS_VIOLATION
。前缀为STATUS
的列表中的所有异常都直接定义为前缀为EXCEPTION
的异常代码。根据{{3}}的文档,它解释了在异常发生时尝试调试异常的过程,最后一步是:
如果未调试进程,或者关联的调试器未处理异常,则系统会根据异常类型提供缺省处理。对于大多数例外,默认操作是调用ExitProcess函数。
所以回答我的问题:
EXCEPTION_STATUS_VIOLATION
。 答案 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
的另一个主题