【问题标题】:Error management for a C computer game [closed]C计算机游戏的错误管理[关闭]
【发布时间】:2013-12-25 10:31:04
【问题描述】:

使用 C 语言编写的电脑游戏会出现什么样的错误以及如何处理它们?对于电脑游戏,我指的是一个对人类生命或“财产”没有任何危险的程序。

我想添加尽可能少的错误处理代码,以使一切尽可能清晰和简单。比如我不想做this,因为this对于一个游戏来说更简单也足够了。

到目前为止,我一直在思考这个问题:

  • 错误:调用malloc时内存不足。

    处理:打印错误信息并调用exit(EXIT_FAILURE);(如this

  • 错误:一个编程错误,即如果正确实施会起作用的东西。

    处理:使用assert 检测(如果失败则中止程序)。

  • 错误:读取损坏的关键文件(例如游戏资源)。

    处理:打印错误信息并调用exit(EXIT_FAILURE);

  • 错误:读取损坏的非关键文件(例如加载保存的游戏)。

    处理:向用户显示消息并要求加载另一个文件。

您认为这是一个合理的方法吗?我应该期待什么其他错误以及处理它们的合理最小方法是什么?

【问题讨论】:

  • 很简单,只要写出完美的代码就不需要处理错误了!
  • 即使我的程序写得很好,也无法避免内存不足(没有更多的内存)和文件写入错误(没有更多的磁盘空间)......
  • 1+ 用于在开始编码之前开始考虑错误处理。
  • 如果您否决/关闭投票,您能否快速评论一下这个问题有什么问题?
  • 反对意见是关于“太宽泛”和“主要基于选项”。由此得出结论,有些人似乎不喜欢关于 SO 的概念性问题。可能你的问题会更适合programmers.stackexchange.com

标签: c error-handling runtime-error


【解决方案1】:

您至少可以预料到您使用的库的文档中提到的那些错误。对于通常至少是 libc 的 C 程序。

查看手册页的ERRORS 部分,了解您将使用的功能。


我也会考虑一下:

我不想做this,因为this对于游戏来说更简单也足够了。

想象一下,您已经通过十几个游戏关卡与自己战斗,然后突然屏幕消失,出现奇怪的 OOM*1-错误消息。而且...... - 你没有保存! DXXM!


*1 内存不足

【讨论】:

    【解决方案2】:

    正如我在评论中已经说过的,我认为这是一个非常广泛的问题。不过,现在是圣诞节,我会尽力提供帮助(以免打扰圣诞老人)。

    一般最佳实践已在@alk 和@user2485710 发布的答案中给出。正如我在 C 中看到的那样,我将尝试为错误处理提供一个通用样板。

    如果不编写完美的代码,你就无法防范一切。完美的代码是无法达到的(有点像微积分中的无穷大),尽管您可以尝试接近。

    如果您尝试放入过多的错误处理代码,将会影响性能。所以,让我定义一下我将称之为简单函数用户函数的东西。

    • 用户函数是可以返回错误值的函数。例如fopen
    • 简单函数是不能返回错误值的函数。例如

      long add(int a, int b) 
      {
          long rv = a; // @alk - This way it shouldn't overflow. :P
      
          return rv + b;
      }
      

    以下是一些需要遵循的规则:

    • 用户函数的所有调用都必须处理返回的错误。
    • 简单函数的所有调用都假定是安全的,因此不需要错误处理。
    • 如果简单函数的参数是受限(即int参数必须在0到9之间)使用assert确保其有效性(除非该值是用户输入的结果,在这种情况下您应该处理它或将其传播为 用户函数)。
    • 如果用户函数的参数是restricted并且它不会导致错误,请执行与上述相同的操作。否则,在没有额外断言的情况下传播它。

    就像your malloc example 一样,您可以包装您的用户函数,代码将优雅地退出您的游戏,从而将它们变成简单函数

    这不会消除所有错误,但应该有助于减少错误,同时牢记性能。测试应该将剩余的错误减少到最低限度。

    请原谅我没有更具体,但是,这个问题似乎要求在 C 中使用通用的错误处理方法。

    最后我要补充一点,测试,无论是单元测试还是其他方式,都是您确保代码正常工作的地方。错误处理不是您可以完全计划的事情,因为一些可能的错误只有在您开始编码后才会显而易见(例如游戏不允许您移动,因为您设法将自己卡在墙内,这应该是不可能的,但由于一些奇怪的爆炸机制而被允许)。但是,可以而且应该计划测试,因为这将揭示您应该在哪里花费更多时间来处理错误。

    【讨论】:

    • 非常感谢您的回答!尤其要记住“用户”和“简单”功能之间的区别。我认为要求对“非关键”程序进行错误处理将是一个非常强的约束。例如,从某种意义上说:由于编程错误导致的错误 => 让它崩溃,而不是不惜一切代价尝试恢复并使其保持活力。
    • 吹毛求疵:如果添加 int aint b 会溢出 int,您的 add() 示例可能会遇到某种错误情况。
    • @alk,该死的,好吧,挑战接受了!
    【解决方案3】:

    我的建议是:

    • 打开编译器的标志来引发错误和警告,让你的编译器尽可能地迂腐,-Wall-Werror-Wextra,例如对于clanggcc来说都是一个好的开始
    • 请确保您知道 undefined behaviour 的含义以及可能触发 UB 的场景是什么,编译器并不总是有帮助,即使所有警告都已打开。
    • 使您的程序模块化,尤其是在内存管理和malloc 的使用方面
    • 确保您的编译器和您选择的标准库都支持您选择的 C 标准

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多