什么是 strerror?
strerror 是 C 标准库中的一个函数,它的主要作用是将一个错误码(一个整数)转换为一个对应的、可读的错误信息字符串。

当你调用系统调用或库函数时,如果发生错误,通常会设置一个全局的变量 errno 来表示具体的错误原因。errno 是一个整数值,1 表示 EPERM(操作不允许),2 表示 ENOENT(没有这样的文件或目录)等,这些数字本身对用户来说并不直观,strerror 就是为了解决这个问题而存在的。
strerror 是 C 语言中处理错误信息的“翻译官”。
函数原型
strerror 函数的原型定义在 <string.h> 头文件中:
char *strerror(int errnum);
参数:

errnum: 你想要查询的错误码,通常就是全局变量errno的值。
返回值:
- 返回一个指向静态分配的字符串的指针,这个字符串描述了
errnum对应的错误信息。 errnum不是一个已知的错误码,函数通常会返回一个类似 "Unknown error" 的字符串。- 重要提示:返回的指针指向的是一个静态内存区域,这意味着:
- 你不应该尝试修改这个字符串。
- 如果你连续调用
strerror,前一次调用返回的字符串内容可能会被后一次调用覆盖,如果你需要长期保存这个字符串,应该使用strdup进行复制,或者自己手动创建一个副本。
使用示例
下面我们通过一个实际的例子来演示 strerror 的用法,我们将尝试打开一个不存在的文件,这会触发错误,然后我们使用 strerror 来打印出具体的错误信息。
示例 1:基本用法
#include <stdio.h>
#include <string.h> // 包含 strerror 函数
#include <errno.h> // 包含 errno 变量
int main() {
FILE *fp;
// 尝试打开一个不存在的文件
fp = fopen("this_file_does_not_exist.txt", "r");
// fopen 返回 NULL,说明打开失败
if (fp == NULL) {
// 全局变量 errno 被自动设置为相应的错误码
// 我们使用 perror 函数来打印错误信息,它会自动调用 strerror
perror("fopen failed");
// perror 打印的内容类似于:fopen failed: No such file or directory
// 或者,我们可以手动调用 strerror 来获取并打印错误信息
printf("Error opening file: %s\n", strerror(errno));
}
return 0;
}
编译和运行结果:
gcc strerror_example.c -o strerror_example ./strerror_example
输出:
fopen failed: No such file or directory
Error opening file: No such file or directory
在这个例子中,fopen 失败后,errno 被设置为 ENOENT(值为 2)。perror 函数内部就调用了 strerror(errno) 来获取 "No such file or directory" 这个字符串,并将其打印出来,我们手动调用的 strerror(errno) 也得到了同样的结果。
与 perror 的关系
strerror 和 perror 是紧密相关的两个函数,它们经常一起出现。
-
*`perror(const char s)`**:
- 它会打印两条信息到标准错误输出。
- 第一条信息是你传入的字符串
s,后面跟一个冒号和一个空格。 - 第二条信息是
strerror(errno)返回的错误描述字符串,后面跟一个换行符。 - 作用:快速、方便地打印出带有你自定义前缀的错误信息。
-
strerror(int errnum):- 它只做一件事:将错误码
errnum转换为字符串。 - 它不负责打印,只负责“翻译”。
- 作用:提供更灵活的错误处理,比如将错误信息记录到日志文件中,或者进行更复杂的格式化。
- 它只做一件事:将错误码
对比:
perror("fopen");->fopen: No such file or directoryprintf("fopen: %s\n", strerror(errno));->fopen: No such file or directoryprintf("Log: Operation failed with error %d (%s)\n", errno, strerror(errno));->Log: Operation failed with error 2 (No such file or directory)
常见错误码与对应信息
下面是一些在 Linux/Unix 系统中常见的 errno 值及其 strerror 返回的字符串:
| 错误码 (值) | 宏定义 | 错误信息 (strerror 返回) | 中文含义 |
|---|---|---|---|
| 1 | EPERM |
Operation not permitted | 操作不允许 |
| 2 | ENOENT |
No such file or directory | 没有文件或目录 |
| 3 | ESRCH |
No such process | 没有此进程 |
| 4 | EINTR |
Interrupted system call | 系统调用被中断 |
| 5 | EIO |
I/O error | 输入/输出错误 |
| 6 | ENXIO |
No such device or address | 没有此设备或地址 |
| 12 | ENOMEM |
Out of memory | 内存不足 |
| 13 | EACCES |
Permission denied | 权限被拒绝 |
| 17 | EEXIST |
File exists | 文件已存在 |
| 22 | EINVAL |
Invalid argument | 无效参数 |
| 28 | ENOSPC |
No space left on device | 设备上没有剩余空间 |
| 32 | EPIPE |
Broken pipe | 管道破裂 |
注意事项
-
线程安全:在传统的 C 库中,
strerror返回的静态字符串可能会导致线程安全问题,因为一个线程的调用可能会覆盖另一个线程的结果,为了解决这个问题,POSIX 标准引入了一个线程安全的版本strerror_r。 -
strerror_r简介:-
strerror_r有两种实现方式(GNU 和 XSI),你需要查阅手册页来确定你的系统使用的是哪一种。 -
它通常需要一个缓冲区作为参数,将错误信息写入这个缓冲区,而不是返回一个静态指针,从而避免了线程安全问题。
-
示例:
#include <string.h> #include <errno.h> char buf[256]; strerror_r(errno, buf, sizeof(buf)); printf("Error: %s\n", buf);
-
| 特性 | 描述 |
|---|---|
| 头文件 | <string.h> |
| 功能 | 将错误码转换为可读的错误字符串。 |
| 参数 | 一个整数错误码(通常是 errno)。 |
| 返回值 | 指向静态错误字符串的指针。不要修改它,如果需要长期保存,请复制它。 |
| 常见用途 | 与 errno 配合使用,通过 perror 或 printf 打印友好的错误信息。 |
| 线程安全 | 基础版本不是线程安全的,推荐使用线程安全的 strerror_r。 |
strerror 是 C 语言编程中处理错误反馈不可或缺的工具,掌握它的使用能让你的程序调试和用户体验都得到显著提升。
