Skip to content

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 的错误处理需要程序员自律:检查返回值、合理设计错误码、及时清理资源,并在适当场合使用断言与信号。

本站内容仅供学习和研究使用。