perror()
函数详解
perror()
是 C 标准库中的一个函数,用于将当前 errno
值对应的错误信息打印到标准错误输出(stderr)。它比手动使用 strerror(errno)
更方便,因为它自动处理了格式化和输出。
函数原型
#include <stdio.h>
#include <errno.h> // 虽然不必须,但通常一起包含
void perror(const char *s);
功能描述
- 读取当前线程的
errno
值 - 查找对应的错误描述字符串(相当于
strerror(errno)
) - 将输出格式化为:
[你提供的字符串]: [错误描述]\n
- 将结果输出到标准错误流(stderr)
使用示例
基本用法
FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
perror("文件打开失败");
// 输出示例: "文件打开失败: No such file or directory"
}
对比 strerror
// 使用 perror
perror("操作失败");
// 等效于使用 strerror
fprintf(stderr, "操作失败: %s\n", strerror(errno));
参数说明
s
: 用户自定义的前缀字符串- 如果为 NULL,则只打印错误描述
- 如果为空字符串(“”),行为与 NULL 相同
- 通常用于说明是哪个操作失败了
特点
- 自动使用当前 errno:不需要手动传递错误码
- 输出到 stderr:符合UNIX工具的错误输出惯例
- 线程安全:在现代实现中是线程安全的
- 包含换行符:自动在末尾添加换行
与 Windows 编程的关系
重要区别:
perror()
只处理标准 C 库设置的errno
- Windows API 错误需要使用
GetLastError()
+FormatMessage()
- 在 Windows 上使用标准C库函数时仍可用
perror()
最佳实践
-
总是包含有意义的上下文:
perror("无法创建日志文件"); // 好 perror(""); // 不好
-
检查错误后立即使用:
if (some_syscall() == -1) { perror("some_syscall failed"); // 立即使用 // 不要在这之间调用其他可能修改errno的函数 }
-
与 exit 结合使用:
if (chdir("/invalid/path") == -1) { perror("致命错误:无法切换目录"); exit(EXIT_FAILURE); }
-
在 Windows 上的替代方案:
#ifdef _WIN32 void win_perror(const char *prefix) { DWORD err = GetLastError(); LPSTR buf = NULL; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPSTR)&buf, 0, NULL); if (buf) { fprintf(stderr, "%s: %s", prefix, buf); LocalFree(buf); } } #endif
常见错误
-
错误时机:
if (open() == -1) { printf("做一些其他事情\n"); // 可能修改errno perror("open failed"); // 可能显示错误的错误信息 }
-
混淆错误源:
CreateFile(...); // Windows API if (失败) { perror("错误"); // 错误!应该用GetLastError() }
-
忽略返回值:
fopen("file", "r"); perror("可能不准确"); // 如果fopen成功,errno的值是未定义的
perror()
是快速简单输出错误信息的便捷工具,特别适合小型工具和快速原型开发。对于更复杂的应用程序,特别是跨平台或需要更精细错误处理的程序,可能需要更强大的错误处理机制。