C 标准库 – errno.h

关键要点

  • <errno.h> 是 C 标准库中的头文件,用于处理程序中的错误。
  • 它定义了 errno 变量,记录系统调用或库函数失败时的错误代码。
  • 研究表明,<errno.h> 提供了一套标准化的错误报告机制,适合调试和错误处理。

简介

<errno.h> 帮助程序员了解函数调用失败的原因。它包含一个叫 errno 的变量,当某些操作出错时,系统会设置这个变量的值,告诉我们发生了什么错误。比如,打开一个不存在的文件时,errno 可能会设置为 ENOENT,表示“没有该文件或目录”。

使用方法

你可以用 <errno.h> 检查错误,比如:

  • 包含头文件:#include <errno.h>
  • 调用函数后,检查 errno 是否有值,比如 if (errno != 0)
  • strerror(errno) 把错误代码转为可读的文字,比如“权限被拒绝”。

注意事项

  • errno 在成功时不会改变,失败时才会被设置。
  • 在多线程程序中,每个线程有自己的 errno,不会互相干扰。
  • 错误代码因操作系统不同可能有差异,建议用宏名(如 EACCES)而非数字。


详细报告:C 标准库 – 中文讲解

C 标准库中的 <errno.h> 头文件是程序错误处理的重要工具,提供了一种标准化的机制来报告和处理运行时错误。它定义了整数变量 errno,由系统调用和某些库函数在发生错误时设置,用于指示错误的类型。以下是详细的中文讲解,涵盖其功能、使用方法、适用场景和注意事项,基于多方研究资料整理。

1. 概述

<errno.h> 是 C 标准库中的一个头文件,主要用于提供错误报告和处理机制。研究表明,它是调试和诊断程序错误的重要工具,尤其在处理系统调用和库函数失败时。

  • 核心功能:定义 errno 变量,这是一个整数类型(int)的可修改左值,程序可以读取和修改它。errno 用于存储最近一次错误的错误代码。
  • 初始化:程序启动时,errno 被设置为零。库函数在成功执行时不会修改 errno,但在发生错误时会将其设置为非零值。
  • 线程安全:在多线程环境中,errno 通常被实现为线程本地存储(TLS),确保每个线程有自己的 errno 副本,不会互相干扰。

2. 错误代码和宏

<errno.h> 头文件定义了一系列表示不同错误代码的宏,这些宏扩展为类型为 int 的整数常量表达式。以下是常见错误代码的列表,基于多方资料整理:

错误代码描述示例场景
EPERM操作不允许尝试以非 root 用户执行特权操作
ENOENT没有该文件或目录打开一个不存在的文件
ESRCH没有该进程尝试操作一个不存在的进程 ID
EINTR中断系统调用信号中断了系统调用
EIOI/O 错误磁盘读写失败
ENXIO没有该设备或地址访问不存在的设备
E2BIG参数列表太长命令行参数超过系统限制
ENOMEM内存不足分配内存失败
EACCES权限被拒绝尝试读取没有权限的文件
EFAULT坏地址访问无效的内存地址
EBUSY资源忙尝试卸载正在使用的文件系统
EEXIST文件已存在尝试创建已存在的文件
EXDEV跨设备链接尝试跨设备移动文件
ENODEV没有该设备访问不存在的设备驱动
ENOTDIR不是目录尝试在文件上使用目录操作
EISDIR是目录尝试对目录执行文件操作
EINVAL无效的参数传递了不合法的参数
ENFILE系统文件表溢出系统打开的文件数达到上限
EMFILE打开的文件太多了进程打开的文件描述符数超过限制
ENOTTY不是终端设备在非终端设备上尝试终端操作
ETXTBSY文本文件忙尝试修改正在执行的程序文件
EFBIG文件太大文件大小超过系统限制
ENOSPC设备上没有空间磁盘已满,无法写入
ESPIPE非法 seek在不支持 seek 的流上尝试定位
EROFS只读文件系统尝试在只读文件系统上写入
EMLINK链接太多文件硬链接数超过系统限制
EPIPE管道破损写入已关闭的管道

需要注意的是,错误代码的具体数值可能因操作系统和 C 库实现而异,因此程序应使用这些宏名(如 ENOENT)而非硬编码数值,以确保跨平台兼容性。

3. 使用方法

使用 <errno.h> 的典型场景是检查函数调用是否成功,并处理可能的错误。以下是一个示例,展示如何处理文件打开失败:

#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    FILE *fp = fopen("nonexistent_file.txt", "r");
    if (fp == NULL) {
        printf("Error opening file: %s\n", strerror(errno));
        // strerror(errno) 将 errno 转换为可读的错误消息
    } else {
        fclose(fp);
    }
    return 0;
}
  • 步骤
  1. 包含 <errno.h> 头文件。
  2. 调用可能失败的函数(如 fopen),检查返回值。
  3. 如果函数失败(例如返回 NULL),检查 errno 的值。
  4. 使用 strerror(errno) 将错误代码转换为可读的字符串,便于调试和日志记录。
  • 注意事项
  • 在调用函数前,可以将 errno 设置为零,以确保检测到函数是否修改了它。
  • 只有当函数明确说明会设置 errno 时,才应检查其值。成功执行的函数不会修改 errno

4. 适用场景

<errno.h> 特别适合以下场景:

  • 错误诊断:用于在程序运行时诊断系统调用或库函数的错误。
  • 调试:帮助开发者快速定位和理解程序中的错误。
  • 跨平台兼容:提供标准化的错误处理机制,确保程序在不同操作系统上的可移植性。

5. 系统和平台相关性

  • POSIX 标准<errno.h> 是 POSIX 标准的一部分,起源于 UNIX 系统。
  • 平台差异
  • 在 Linux(如 2.4.20-18 内核)中,<errno.h> 通常位于 /usr/include/asm
  • 在 Windows 中,套接字编程使用 WSAGetLastError() 而非 errno,历史上曾重新定义 BSD 错误常量(如 ECONNREFUSED 变为 WSAECONNREFUSED),但后来因冲突被注释。

6. 注意事项

  • 性能影响:检查 errno 的开销很小,适合频繁使用。
  • 线程安全:在多线程程序中,errno 是线程本地存储,确保线程隔离。
  • 避免依赖数值:由于错误代码可能因平台不同而变化,程序应使用宏名而非硬编码数值。

7. 研究背景与资料来源

本报告基于多方研究资料整理,包括以下来源:

这些资料确保了信息的全面性和准确性,涵盖了 2025 年 7 月 6 日前的最新研究成果。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注