错误处理与安全函数
概念说明
C 语言默认没有像很多高级语言那样统一的异常机制。
大多数标准库函数会通过返回值告诉你“成功还是失败”,必要时再借助 errno 补充更具体的错误原因。
所以,C 里的错误处理重点不是“出错以后再说”,而是每次调用都及时检查结果。 文件操作、内存申请、字符串处理、格式化输入输出,都是最应该养成这个习惯的地方。
这里所谓的“安全函数”,更准确地说,是“边界意识更强的写法”。
有时它表现为使用 snprintf、fgets、strtol 这类更容易做长度和错误检查的接口;有时也包括某些平台提供的 _s 系列函数,但后者并不是所有环境都统一支持。
语法/规则
- 调用可能失败的函数后,要先检查返回值,再决定是否继续执行。
errno只有在函数已经明确失败时才有意义,不应在成功路径里随意读取它。- 如果错误信息后面还要继续使用,最好先把
errno保存到局部变量中,再调用strerror或perror。 - 错误信息应优先输出到
stderr,不要和正常结果混在stdout中。 - 程序结束时可用
EXIT_SUCCESS和EXIT_FAILURE表达退出状态,比直接写数字更清晰。 - 读取字符串时,
fgets往往比无长度控制的gets或%s更稳妥。 - 格式化拼接字符串时,
snprintf通常比sprintf更适合做边界控制。 - 解析数字时,
strtol、strtod一般比atoi、atof更容易检查错误。 _s系列函数属于可选或平台相关能力,写可移植代码前应先确认支持情况。
示例
| |
输出结果:
| |
不同平台下的错误号和错误文本可能略有差异,但整体用法是一致的。
常见错误
- 读取
errno之前不先确认函数是否失败,导致把旧错误当成新错误。 - 直接把错误输出到
stdout,让正常输出和错误输出混在一起。 - 使用
sprintf、strcpy、strcat这类接口时完全不考虑目标缓冲区大小。 - 直接用
atoi解析用户输入,却没有检测转换失败或溢出的情况。 - 以为
_s后缀函数在所有平台都可直接使用,结果换编译器后无法通过编译。