linux系统编程之错误处理:perror,strerror和errno
1,在系统编程中错误通常通过函数返回值来表示,并通过特殊变量errno来描述。
errno这个全局变量在<errno.h>头文件中声明如下:extern int errno;
errno是一个由POSIX和ISO C标准定义的符号,看(用)起来就好像是一个整形变量。当系统调用或库函数发生错误的时候,比如以只读方式打开一个不存在的文件时,它的值将会被改变,根据errno值的不同,我们就可以知道自己的程序发生了什么错误,然后进行相应的处理。
为什么,要强调errno看起来好像是一个整形变量呢?因为有的标准(如ISO C)只规定了errno的作用,而没有规定它的实现方式,它可能被定义成一个变量,也有可能被定义成一个宏,这个具体要看编译器自己的实现。早些时候,POSIX.1曾把errno定义成extern int errno这种形式,但现在这种方式比较少见了。因为以这种形式来实现errno,在多线程环境下errno变量是被多个线程共享的,这样可能线程A发生某些错误改变了errno的值,线程B虽然没有发生任何错误,但是当它检测errno的值的时候,线程B会以为自己发生了错误。所以现在errno在Linux中被实现成extern int * __errno_location(void): #define errno (*__errno_location()),这样每个线程都有自己的errno,不会再发生混乱了。
关于errno有三点需要特别注意:
1、如果系统调用或库函数正确执行的话,errno的值是不会被清零(置0,注意这里是不会被清零,不是不会被改变)的,假若执行函数A的时候发生了错误errno被改变,接下来直接执行函数B,如果函数B正确执行的话,errno还保留函数A发生错误时被设置的值。所以,在利用errno之前,最好先对函数的返回值进行判断,看是否发生了错误,返回值错误再利用errno判断时哪里发生了错误。所以如果一个函数无法从返回值上判断正误,而只能通过errno来判断出错,那你在调用它之前必须手动将errno清零!
2、系统调用或库函数正确执行,并不保证errno的值不会被改变!
3、任何错误号(即发生错误时errno的取值)都是非0的。
综上所述,当需要用errno来判断函数是否正确执行的时候,最好先将errno清零,函数执行结束时,通过其返回值判断函数是否正确执行,若没有正确执行,再根据errno判断时哪里发生了错误。
2. 错误处理函数
- perror
- strerror
perror和strerror函数都是用来打印错误提示信息的,它们的原型分别是:
#include <stdio.h>
void perror(const char *s);
它先打印s指向的字符串,然后输出当前errno值所对应的错误提示信息,例如当前errno若为12,调用perror("ABC"),会输出"ABC: Cannot allocate memory"。
测试程序:
#include <stdio.h>
#include <unistd.h> int main(void)
{
int fd = ;
int ret;
ret = close(fd);
if(ret == -)
perror("close error");
return ;
}
测试结果:

#include <string.h>
char *strerror(int errnum);
它返回errnum的值所对应的错误提示信息,例如errnum等于12的话,它就会返回"Cannot allocate memory"。
测试程序:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> int main(void)
{
int fd = ;
int ret;
ret = close(fd);
if(ret == -)
fprintf(stderr, "close error with msg is: %s\n",strerror(errno));
return ;
}
测试结果:

注:本文参考http://blog.csdn.net/yandianxun/article/details/6676248
linux系统编程之错误处理:perror,strerror和errno的更多相关文章
- linux系统编程之错误处理
在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 #ifndef _ERRNO_H /* ...
- linux系统编程之错误处理机制
在讲解liunx错误处理机制之前我们先来看一段代码: #include<sys/types.h> #include<sys/stat.h> #include<fcntl. ...
- Linux系统编程@进程通信(一)
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
- Linux系统编程【转】
转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...
- linux系统编程之文件与io(一)
经过了漫长的学习,C语言相关的的基础知识算是告一段落了,这也是尝试用写博客的形式来学习c语言,回过头来看,虽说可能写的内容有些比较简单,但是个人感觉是有史起来学习最踏实的一次,因为里面的每个实验都是自 ...
- Linux C 程序 文件操作(Linux系统编程)(14)
文件操作(Linux系统编程) 创建一个目录时,系统会自动创建两个目录.和.. C语言实现权限控制函数 #include<stdio.h> #include<stdlib.h> ...
- linux系统编程之文件与io(五)
上一节中已经学习了文件描述符的复制,复制方法有三种,其中最后一种fcntl还并未使用到,关于这个函数,不光只有复制文件描述符的功能,还有其它一些用法,本节就对其进行一一剖析: fcntl常用操作: 这 ...
- Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道
Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...
- Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号
Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...
随机推荐
- 通过Github Pages在线查看百度前端技术学院完成的任务成果
前言 .note-content {font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHe ...
- Usage of “symmetrical” and “symmetric”
What is the appropriate usage of "symmetrical" and "symmetric" (using the geomet ...
- 运行php网站需要安装什么
php的运行环境: 为了能够运行php,有以下两种方法: 1. 使用支持php和MySQL的web主机(): 2. 本机(自己电脑)安装web服务器,然后安装MySQL和php. web虚拟主机: 大 ...
- 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr
auto_ptr<string> p1(new string ("auto") : //#1 auto_ptr<string> p2; //#2 p2 = ...
- Django的models介绍
我们一般会在创建表的类中写一个__str__方法,就会为为了打印这个对象不会打印一大堆的对象的内存地址,而是我们想要他返回的信息,方便我们更直观的知道这个对象是谁,方便显示.比如下面的例子 from ...
- 接触mybatis使用
1.mybatis mybatis是一个自定义sql.存储过程和高级映射的持久层框架,是Apache下的顶级项目. mybatis可以让程序员将主要精力放在sql上,通过mybatis提供的映射方式. ...
- web前端js 实现打印操作
转载来源:https://www.cnblogs.com/potatog/p/7412905.html 一.打印当前页面指定元素中的内容 方式一:直接使用window.print(); (1)首先获得 ...
- 将html转换成image图片png格式
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics ...
- DB2数据库常用命令数据库学习
DB2数据库常用命令数据库学习你可以用 get snapshot for locks on XXX 看是那个表锁了,再从相关的操作去查原因吧 db2pd -d 库名 -locks和db2pd -d 库 ...
- Legendre多项式
Legendre多项式 时间限制: 1 Sec 内存限制: 128 MB 题目描述 Legendre多项式的递归公式