当前位置: 首页 > article >正文

Linux文件IO(四)-返回错误处理与errno详解

1.前言

在上一文章中,给大家编写了很多的示例代码,大家会发现这些示例代码会有一个共同的特点,那就是当判断函数执行失败后,会调用 return 退出程序,但是对于我们来说,我们并不知道为什么会出错,什么原因导致此函数执行失败,因为执行出错之后它们的返回值都是-1。

难道我们真的就不知道错误原因了吗?其实不然,在 Linux 系统下对常见的错误做了一个编号,每一个编号都代表着每一种不同的错误类型,当函数执行发生错误的时候,操作系统会将这个错误所对应的编号赋值给 errno 变量,每一个进程(程序)都维护了自己的 errno 变量,它是程序中的全局变量,该变量用于存储就近发生的函数执行错误编号,也就意味着下一次的错误码会覆盖上一次的错误码。所以由此可知道,程序中调用函数发生错误的时候,操作系统内部会通过设置程序的 errno 变量来告知调用者究竟发生了什么错误!

errno 本质上是一个 int 类型的变量,用于存储错误编号,但是需要注意的是,并不是执行所有的系统调用或 C 库函数出错时,操作系统都会设置 errno,那我们如何确定一个函数出错时系统是否会设置 errno 呢?

其实这个通过 man 手册便可以查到,譬如以 open 函数为例,执行"man 2 open"打开 open 函数的帮助信息,找到函数返回值描述段,如下所示:

从图中红框部分描述文字可知,当函数返回错误时会设置 errno,当然这里是以 open 函数为例,其它的系统调用也可以这样查找,大家可以自己试试!

在我们的程序当中如何去获取系统所维护的这个errno变量呢?只需要在我们程序当中包含<errno.h>头文件即可,你可以直接认为此变量就是在<errno.h>头文件中的申明的,好,我们来测试下:

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

int main(void)
{
	printf("%d\\n", errno);
	return 0;
}

以上的这段代码是不会报错的,大家可以自己试试!

2.strerror 函数

前面给大家说到了 errno 变量,但是 errno 仅仅只是一个错误编号,对于开发者来说,即使拿到了 errno也不知道错误为何?还需要对比源码中对此编号的错误定义,可以说非常不友好,这里介绍一个 C 库函数strerror(),该函数可以将对应的 errno 转换成适合我们查看的字符串信息,其函数原型如下所示(可通过"man 3 strerror"命令查看,注意此函数是 C 库函数,并不是系统调用):

#include <string.h>
char *strerror(int errnum);

首先调用此函数需要包含头文件<string.h>。

函数参数和返回值如下:

errnum:错误编号 errno。

返回值:对应错误编号的字符串描述信息。

测试

接下来我们测试下,测试代码如下:

//示例代码 3.2.1 strerror 测试代码

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(void)
{
		int fd;

		/* 打开文件 */
		fd = open("./test_file", O_RDONLY);
		if (-1 == fd) {
				printf("Error: %s\\n", strerror(errno));
				return -1;
		}
		close(fd);
		return 0;
}

编译源代码,在 Ubuntu 系统下运行测试下,在当前目录下并不存在 test_file 文件,测试打印结果如下:

从打印信息可以知道,strerror 返回的字符串是"No such file or directory",所以从打印信息可知,我们就可以很直观的知道 open 函数执行的错误原因是文件不存在!

3.perror 函数

除了 strerror 函数之外,我们还可以使用 perror 函数来查看错误信息,一般用的最多的还是这个函数,用此函数不需要传入 errno,函数内部会自己去获取 errno 变量的值,调用此函数会直接将错误提示字符串打印出来,而不是返回字符串,除此之外还可以在输出的错误提示字符串之前加入自己的打印信息,函数原型如下所示(可通过"man 3 perror"命令查看):

#include <stdio.h>

void perror(const char *s);

需要包含<stdio.h>头文件。

函数参数和返回值含义如下:

s:在错误提示字符串信息之前,可加入自己的打印信息,也可不加,不加则传入空字符串即可。

返回值:void 无返回值。

测试

接下来我们进行测试,测试代码如下所示:

//示例代码 3.2.2 perror 测试代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
		int fd;
		
		/* 打开文件 */
		fd = open("./test_file", O_RDONLY);
		if (-1 == fd) {
			perror("open error");
			return -1;
		
		
		close(fd);
		return 0;
}

编译源代码,在 Ubuntu 系统下运行测试下,在当前目录下并不存在 test_file 文件,测试打印结果如下:

从打印信息可以知道,perror 函数打印出来的错误提示字符串是"No such file or directory",跟 strerror 函数返回的字符串信息一样,"open error"便是我们附加的打印信息,而且从打印信息可知,perror 函数会在附加信息后面自动加入冒号和空格以区分。

以上给大家介绍了 strerror、perror 两个 C 库函数,都是用于查看函数执行错误时对应的提示信息,大家用哪个函数都可以,这里推荐大家使用 perror,在实际的编程中这个函数用的还是比较多的。


http://www.kler.cn/a/313159.html

相关文章:

  • 【Linux篇】面试——用户和组、文件类型、权限、进程
  • mysql 快速解决死锁方式
  • 【RabbitMQ】08-延迟消息
  • Matlab实现鹈鹕优化算法(POA)求解路径规划问题
  • Java项目实战II基于Spring Boot的药店管理系统的设计与实现(开发文档+数据库+源码)
  • Go常见框架对比
  • 【数据结构与算法】LeetCode:双指针法
  • 基于STM32F103C8T6单片机的DDS信号源设计
  • 海洋大地测量基准与水下导航系列之二国外海底大地测量基准和海底观测网络发展现状(上)
  • mac中git操作账号的删除
  • 【linux】4张卡,坏了1张,怎么办?
  • ActivityManagerService Activity的启动流程(2)
  • Windows10、CentOS Stream9 环境下安装kafka_2.12-3.6.2记录
  • Oracle数据库pl/sql显式抛出异常
  • Python 项目实践:文件批量处理
  • 软硬件项目运维方案(Doc原件完整版套用)
  • CSP-CCF★★★201909-2小明种苹果(续)★★★
  • 【Linux】:信号的保存和信号处理
  • 【C++掌中宝】深入解析C++命名空间:有效管理代码的利器
  • 文心快码、通义灵码、腾讯云AI代码助手、豆包MarsCode 四大国产AI编程助手对比
  • 前端中常见的三种存储方式Cookie、localStorage 和 sessionStorage。
  • CompletableFuture-详解使用及源码解析
  • 洗衣机制造5G智能工厂物联数字孪生平台,推进制造业数字化转型
  • 《nmap 命令全解析:网络探测与安全扫描的利器》
  • 2024最新最全:超详细Nmap使用技巧(非常详细)零基础入门到精通,收藏这一篇就够了
  • 【delphi】正则判断windows完整合法文件名,包括路径