【问题标题】:Should we error check every call in C?我们应该对 C 中的每个调用进行错误检查吗?
【发布时间】:2018-01-14 03:21:56
【问题描述】:

当我们编写 C 程序时,我们会调用 malloc 或 printf。但是我们需要检查每个电话吗?您使用什么准则?

例如

char error_msg[BUFFER_SIZE];
if (fclose(file) == EOF) {
    sprintf(error_msg, "Error closing %s\n", filename);
    perror(error_msg);
}

【问题讨论】:

  • 我不检查printf,如果失败了,那么你的电脑确实有问题。 fprintf我检查,但只有在写操作是必要的情况下,如果是日志,我不检查。 malloc & co,我总是检查它们,即使有时这很烦人。
  • 你不能这么说。作为一个经验法则,你应该检查所有可能出错的地方——如果是这样的话——当你有一个策略来处理它时。例如,在托管系统上检查 malloc() 通常会导致程序终止,因为如果没有足够的内存,您的程序将无法按预期运行。
  • 即使在 malloc 失败的情况下,您至少可以预先设置好,以便可以优雅地终止。
  • 根据我的经验,malloc() 失败的最常见原因不是堆空间不足,而是请求的内存大小是一个愚蠢的数字 - 通常是因为一些 int被指针值覆盖或未初始化。因此,在那里进行检查至少可以阻止腐烂,尽管除了报告问题并退出之外您无能为力。
  • 关于调用fclose()的代码块。以下对sprintf() 的调用将更改errno 中的值,因此对perror() 的调用应该在对sprintf() 的调用之前

标签: c error-handling


【解决方案1】:

您的问题的答案是:“随心所欲”,没有书面规则,但正确的问题是“如果失败,用户想要什么”。

让我解释一下,例如,如果你是一个正在编写测试程序的学生,那么绝对不需要检查错误:这可能是浪费时间。

现在,如果您的代码可能被其他人分发或使用,那就完全不同了:设身处地为未来的用户着想。当应用程序出现问题时,您更喜欢哪种消息:

Core was generated by `./cut --output-d=: -b1,1234567890- /dev/fd/63'.
Program terminated with signal SIGSEGV, Segmentation fault.

MySuperApp failed to start MySuperModule because there is not enough space on the disk.
Try to free space on disk, then relaunch the app. 
If this error persists contact us at support@mysuperapp.com

由于它已经在评论中解决,您必须考虑两种类型的错误:

  • 致命错误会杀死您的程序(应用程序/服务器/站点/无论它是什么)。它通过崩溃或将其置于某种无法完成可用工作的状态而使其无法使用。例如内存分配、磁盘空间...
  • 非致命错误是一种出现问题的错误,但程序可以继续执行它应该执行的操作。例如未找到文件,为其他未请求错误的用户提供服务。

来源:https://www.quora.com/What-is-the-difference-between-an-error-and-a-fatal-error

【讨论】:

    【解决方案2】:

    如果您的程序行为必须在检测到错误时表现不同,请进行错误检查。让我用一个例子来说明这一点:假设您在程序中使用了一个临时文件,并且您使用unlink(2) 系统调用在程序结束时擦除该临时文件。您是否检查文件是否已成功擦除?让我们用一些常识来分析这个问题:如果你检查错误,你是否能够(在程序内部)做一些替代的事情来解决这个问题?这是不常见的(如果您创建了文件,您将无法删除它的情况很少见,但在这之间的时间可能会发生一些事情 --- 例如,目录权限的更改禁止您再在目录上写入)但在这种情况下你能做什么?在这种情况下是否可以使用不同的方法来擦除临时文件。可能不会……所以检查(在这种情况下)unlink(2) 系统调用中可能出现的错误几乎是没有用的。

    当然,这并不总是适用,您必须在编程时使用常识。应始终考虑有关写入文件的错误,因为它们属于访问权限或主要属于完整的文件系统(在这种情况下,即使尝试生成日志消息也可能是无用的,因为您已经填满了磁盘 --- 或者没有,取决于)如果可以忽略完整的文件系统错误,您是否总是知道要避免的精确环境细节。假设您必须连接到程序中的服务器。 connect(2) 系统调用失败是否应该采取行动?可能在大多数情况下,至少必须向用户发送一条带有协议错误(或失败原因)的消息......假设一切顺利可以节省您在原型中的时间,但是您有以应对生产程序中可能发生的情况。

    【讨论】:

      【解决方案3】:

      当我想使用函数的返回值时,建议在使用前检查返回值 例如指针返回地址也可以为空。所以建议在使用前保持空检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-07
        • 2011-02-23
        • 1970-01-01
        • 2010-10-25
        相关资源
        最近更新 更多