C 错误处理
C 语言没有异常机制,错误处理主要通过返回码、全局变量 errno 与信号等方式实现。本章介绍常见的错误处理模式与最佳实践。
1. 返回码模式
多数 C 标准库函数使用特殊返回值表示错误:
c
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
printf("Failed to open file\n");
return -1;
}2. errno 全局变量
在 <errno.h> 中定义,许多系统调用出错时会设置 errno:
c
#include <errno.h>
#include <string.h>
FILE *fp = fopen("nonexistent.txt", "r");
if (!fp) {
printf("Error: %s\n", strerror(errno));
}3. 设计返回码约定
- 成功通常返回 0 或正值
- 失败返回负值或特殊值(如 -1、NULL)
- 通过指针参数返回实际结果
c
int divide(double a, double b, double *result) {
if (b == 0.0) return -1; // 除零错误
*result = a / b;
return 0; // 成功
}4. 错误传播与清理
c
int process_file(const char *filename) {
FILE *fp = fopen(filename, "r");
if (!fp) return -1;
char *buf = malloc(1024);
if (!buf) {
fclose(fp);
return -2; // 内存分配失败
}
// 处理逻辑...
free(buf);
fclose(fp);
return 0;
}5. 断言(assert)
用于调试时检查程序假设:
c
#include <assert.h>
void sort_array(int *arr, size_t n) {
assert(arr != NULL);
assert(n > 0);
// 排序实现...
}发布版本通过 #define NDEBUG 禁用断言。
6. 信号处理(signal.h)
用于异步事件处理,如段错误、中断等:
c
#include <signal.h>
void sigint_handler(int sig) {
printf("Caught SIGINT\n");
exit(0);
}
signal(SIGINT, sigint_handler);7. 小结
C 的错误处理需要程序员自律:检查返回值、合理设计错误码、及时清理资源,并在适当场合使用断言与信号。