3

我正在编写一个游戏,其中许多不同的条件都可能导致失败,例如图像或着色器无法加载,OpenGL 无法获得有效的上下文等。

在一个理想的世界中,我想以我认为适用于 C 的方式使用退出代码,即非零用于失败条件。但是,有一些因素会影响到这一点:

  • 在使用非零退出代码时,atexit()不调用,不幸的是我的程序清理是通过我喜欢的单个atexit()注册分层处理的。main()
  • 我突然想到,考虑到应用程序的性质 - 与批处理程序不同,游戏具有不确定的运行时间 - 可能永远不会有实际使用退出代码的实际情况。它不像 Makefile 调用的命令行图像转换器,它需要通过其退出代码知道程序是成功还是失败,从而确定是否继续构建。可能性是,如果程序在运行时出现任何问题,例如丢失文件,那是我自己解决的问题,然后顺利进行。

在我的情况下,可以提出和反对使用非零退出代码的哪些论据?

4

1 回答 1

8

触发注册atexit()函数

与您的问题相反,atexit()即使程序尝试向主机环境返回非零终止状态,仍会调用注册的函数。无论给定的值如何,对的调用exit()main()返回的函数都将触发使用 注册的函数。atexit()

例子:

#include <stdlib.h>
#include <stdio.h>

void print_stuff(void)
{
    puts("Stuff");
}

int main(void)
{
    atexit(print_stuff);
    exit(1);
}

这将打印Stuff,即使1返回。

技术细节

按照 ISO C 标准,注册的函数在atexit()被调用后被exit()调用。以下情况也被定义为调用exit()(并因此触发用 注册的函数atexit()):

  1. main()返回等价于调用exit()

  2. 在最后一个线程调用之后thrd_exit()exit(EXIT_SUCCESS)被调用。

以下是可能的实现定义的调用来源exit()

  1. 的默认信号处理程序SIGTERM

  2. 使用前的默认约束处理程序set_constraint_handler_s()

该标准提到了以下情况exit()以及对注册函数的调用atexit()被规避:

  1. 一个未处理的SIGABRT或已SIGABRT完成由注册的函数处理的signal(). SIGABRT可以提高abort()

  2. 呼唤_Exit()

  3. 呼唤quick_exit()

在某些情况下,您实现的宿主环境可能会终止程序而无需调用已注册的函数atexit(),例如在段错误之后

关于游戏的退出代码

您选择的退出代码对于游戏来说应该没有太大影响。是的,您不会依赖 shell 脚本来运行游戏并向用户报告错误。对于像 Linux 这样的系统,错误反馈可能以对话框弹出、日志或标准错误的形式更有用。

于 2015-08-06T20:08:23.167 回答