编程后端C开发者

如何在使用C标准库函数时处理错误?使用errno的具体情况是什么,何时更好地使用返回码,如何避免错误的处理?

用 Hintsage AI 助手通过面试

答案。

问题的历史

在C语言中,错误处理一直是开发者的任务。标准库中没有异常,错误通过返回码或全局变量errno返回(开始使用于1970年代的UNIX,后续为POSIX和ANSI C)。这些机制今天仍用于在异常情况下控制执行流。

问题

在使用标准函数(文件操作、内存分配、字符串函数)时,错误可能在没有特别控制的情况下不易察觉。错误处理不当——忽略返回码、不正确地解释errno、缺乏资源清理——会导致程序运行不正确、崩溃和安全漏洞。

解决方案

正确的错误处理要求必须分析函数返回的值,使用errno仅在失败后,及提供信息丰富的错误输出。返回码适用于内部函数——允许无全球副作用的处理。errno更常用于系统调用和标准库函数。每次潜在危险的操作后,都要分析返回结果,而全局状态(errno)不应被中间调用覆盖。

代码示例:

#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "错误: %s ", strerror(errno)); } return f; }

关键特点:

  • errno仅用于诊断在系统调用/标准函数中发生的错误。
  • 在函数内部返回int错误码是方便的,零代表成功,负数或特殊值代表失败。
  • 重要的是在没有错误的情况下不要依赖errno的值。

带陷阱的问题。

可以将errno用于用户定义函数,以便向上报告错误吗?

不可以,errno仅用于标准库和系统调用。它是全局的,可以在任何地方被重写,不适合自己的函数。

在每次调用函数之前必须设置errno吗?

不必,但建议在调用之前重置errno(例如,设置为零),如果计划分析更改的话。并不是每个函数在成功时都会改变errno,仅在错误时才会。

errno = 0; ... 调用危险函数 ...

可以在任何函数之后信任errno吗?

仅适用于那些根据标准在失败时明确设置errno的函数。许多标准库函数在成功时不会触碰errno。文档是你的朋友。

常见错误和反模式

  • 忽略函数的返回码(例如,fopen、malloc、write)。
  • 在使用errno的值之前重写它。
  • 在项目中使用errno来处理自己的错误。

生活中的示例

负面案例

打开文件时不检查结果,错误没有被分析,程序在缺少文件时运行不正确:

优点:

  • 更少的代码,简单场景下运行迅速。

缺点:

  • 当错误发生时出现模糊的崩溃,无法进行诊断。

正面案例

在每个关键函数后检查结果,如出错则输出详细信息,结合strerror(errno),程序正确终止:

优点:

  • 程序易于维护和调试,稳定性高。

缺点:

  • 代码略多,复杂度稍高。