errno.h
<errno.h> 定义 errno 变量和错误码宏。当标准库函数失败时,通常设置 errno 指示错误原因。errno 是线程局部变量(C11 起),多线程程序中可以安全使用。
基本用法
#include <errno.h>
#include <stdio.h>
#include <string.h>
FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
printf("Error: %s (errno=%d)\n", strerror(errno), errno);
/* Error: No such file or directory (errno=2) */
}
常见错误码
| 错误码 | 含义 |
|---|---|
EDOM | 数学域错误(如 sqrt(-1)) |
ERANGE | 结果超出范围(如 pow(10, 1000)) |
EILSEQ | 非法序列(宽字符转换) |
ENOMEM | 内存不足(POSIX) |
EINVAL | 无效参数(POSIX) |
使用场景
数学函数:
#include <math.h>
#include <errno.h>
errno = 0; /* 清除之前错误 */
double result = sqrt(-1.0);
if (errno == EDOM) {
printf("Domain error\n");
}
字符串转换:
#include <stdlib.h>
#include <errno.h>
errno = 0;
char *end;
long val = strtol("99999999999999999999", &end, 10);
if (errno == ERANGE) {
printf("Overflow\n");
}
线程安全:
/* C11 起 errno 是线程局部 */
/* 每个线程有自己的 errno */
常见错误
不重置 errno:
/* 错误:errno 可能保留旧值 */
double r = sqrt(-1.0);
if (errno == EDOM) { /* 可能误判 */
}
/* 正确 */
errno = 0;
double r = sqrt(-1.0);
if (errno == EDOM) {
}
假设 errno 只增不减:
/* 错误:某些函数成功时不重置 errno */
errno = 0;
func1(); /* 失败,errno=2 */
func2(); /* 成功,但 errno 可能仍为 2 */
if (errno != 0) { /* 误判 func2 失败 */
}
最佳实践
- 调用可能失败的函数前重置
errno - 用
strerror(errno)获取错误描述 - 只检查你关心的函数的 errno
- 多线程程序依赖 C11 或平台保证
- 不假设 errno 的初始值