来自AI回答
errno、strerror()、perror() 的关系与区别
这三个是 C/C++ 中用于处理系统调用或库函数错误的机制:
errno — 错误码变量
- 是一个全局变量(或线程局部变量),定义在
<errno.h>中 - 当系统调用或某些库函数出错时,会设置
errno为一个正整数错误码 - 成功时不会清除
errno,因此应在调用可能失败的函数前将其设为0
strerror() — 错误码转字符串
- 函数原型:
char* strerror(int errnum); - 将
errno错误码转换为可读的错误描述字符串 - 返回的字符串是静态缓冲区,后续调用可能被覆盖(非线程安全)
- 有线程安全版本
strerror_r()
perror() — 直接打印错误信息
- 函数原型:
void perror(const char* s); - 自动使用当前的
errno,将自定义前缀 + 错误描述输出到stderr - 相当于
fprintf(stderr, "%s: %s\n", prefix, strerror(errno));
#include <cstdio>
FILE* f = fopen("nonexist.txt", "r");
if (!f) {
perror("打开文件失败"); // 输出: 打开文件失败: No such file or directory
}典型用法对比
| 功能 | errno |
strerror() |
perror() |
|---|---|---|---|
| 作用 | 存储错误码 | 错误码 → 字符串 | 直接打印错误信息 |
| 输出位置 | 不输出 | 返回字符串 | stderr |
| 灵活性 | 可自行判断 | 可自定义输出格式 | 简单快速打印 |
// 组合使用示例
if (open("file.txt", O_RDONLY) == -1) {
// 方式1: 使用 perror 直接打印
perror("open失败");
// 方式2: 使用 strerror 自定义输出
std::cerr << "open失败: " << strerror(errno) << std::endl;
// 方式3: 仅获取错误码做逻辑判断
if (errno == ENOENT) {
std::cout << "文件不存在" << std::endl;
}
}注意事项
errno在成功时不会被清除,需要手动置零或通过返回值判断是否出错- C++11 后
errno是线程局部存储,各线程独立 - 推荐在 C++ 中用
std::error_code(C++11) 或std::system_error作为更现代的替代