Linux下错误处理依赖返回值、errno和信号机制:系统调用失败查errno并立即处理;严重错误用sigaction捕获SIGSEGV等信号并安全退出;逻辑错误靠函数返回值与状态码主动控制。

Linux 下函数内部捕获并处理错误,核心不是“try-catch”式异常机制(C 语言本身不支持),而是依赖系统调用的返回值 + errno 全局变量 + 信号(signal)机制三类方式,按错误类型区分使用。
系统调用失败:查 errno 并用 strerror 解读
绝大多数 Linux 系统 API(如 open()、read()、malloc() 等)在出错时返回 -1 或 NULL,并自动设置全局变量 errno 为具体错误码。你需要:
- 包含头文件:
#include <errno.h>和#include <string.h> - 检查返回值是否为错误标志(如 -1、NULL)
- 立即读取
errno—— 注意:它可能被后续任意系统调用覆盖,不能延后读取 - 用
strerror(errno)获取可读字符串,或直接比对宏(如if (errno == EACCES))
示例:
int fd = open("/tmp/data.txt", O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open failed: %s (errno=%d)\n", strerror(errno), errno);
// 可进一步分支处理:EACCES → 检查权限;ENOENT → 提示文件不存在
}运行时严重错误:捕获 SIGSEGV、SIGBUS 等信号
段错误(访问非法内存)、总线错误等不会返回 errno,而是触发同步信号。需在程序启动时注册信号处理器:
- 用
sigaction()(优于过时的signal())注册SIGSEGV、SIGBUS、SIGABRT等 - 在 handler 中调用
backtrace()获取调用栈(需编译加-g) - 配合
backtrace_symbols()或addr2line定位源码行号 - 注意:信号处理函数中只能调用异步信号安全函数(如
write()、_exit()),避免用printf()、malloc()
关键点:这不是“恢复执行”,而是记录现场 + 安全退出,防止崩溃无迹可寻。
自定义逻辑错误:靠返回值与状态码主动控制
C 函数自身无法抛出异常,所以设计时应明确约定错误返回方式:
- 返回负整数(如 -1、-EINVAL)表示失败,正数/0 表示成功
- 通过指针参数传出详细错误信息(如
int myfunc(int *out_val, char **errmsg)) - 结合
errno设置(仅当模拟系统调用语义时),增强一致性 - 调用方必须检查返回值——不检查就等于放弃错误处理
例如一个封装 malloc 的函数:
void* safe_malloc(size_t size) {
void *p = malloc(size);
if (!p) {
errno = ENOMEM;
return NULL;
}
return p;
}注意事项与避坑点
容易忽略但关键的细节:
-
errno是线程局部的(每个线程独立副本),多线程下无需额外保护 - 不要假设未出错时
errno保持不变——它的值在成功调用后是未定义的 - 信号处理中禁止调用非异步信号安全函数(
printf、malloc、pthread_mutex_lock都不行) - shell 脚本里用
trap捕获的是进程级信号(如SIGINT),不适用于 C 函数内部逻辑错误


















