2019-03-19 16:43:46 rikeyone 阅读数 320

Linux系统函数失败后都会返回一个负值,并且整形变量errno通常被设置为错误码。我们在使用错误码时,需要包含如下头文件

#include <errno.h>

errno只在函数返回错误时才有意义,当函数执行正常返回时并不会重置errno,因此此时的errno是不能作为错误处理的。
errno是一个int型变量,除了直接使用该变量,还有两个和其相关的API可以方便的查看错误类型:

#include <stdio.h>
void perror(const char *msg);

这个函数会先打印msg信息,然后再输出对应的error类型。

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

这个函数把errno字符串化,输出对应的错误类型字符串。

示例

 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 
 int main(int argc, char *argv[])
 {
     errno = EINVAL;
     printf("Error:%s, errno:%d\n", strerror(errno), errno);
     perror(argv[0]);
     exit(0);
 }

运行结果:

$ gcc error.c -o error
$ ./error
Error:Invalid argument, errno:22
./error: Invalid argument
2016-01-22 16:14:56 gatieme 阅读数 3264

在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。

以下主要来自2.6.32的内核代码中的/usr/include/asm-generic/errno.h及errno-base.h,输出错误原因定义归纳整理如下,我们可以使用如下代码输出

/*************************************************************************
    > File Name: 0.c
    > Author: GatieMe
    > Mail: ftcl@163.com
    > Created Time: Sat 23 Jan 2016 12:07:51 AM CST
 ************************************************************************/

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


int main(int argc, char ** argv)
{
    int i = 0;
    for(i = 0; i < 256; i++)
    {
        printf("| %02d | %s |\n", i, strerror(i));
    }
    return 0;
}

注意

perror( ) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno 的值来决定要输出的字符串。

当你调用”某些”函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

errno 描述
00 Success
01 Operation not permitted
02 No such file or directory
03 No such process
04 Interrupted system call
05 Input/output error
06 No such device or address
07 Argument list too long
08 Exec format error
09 Bad file descriptor
10 No child processes
11 Resource temporarily unavailable
12 Cannot allocate memory
13 Permission denied
14 Bad address
15 Block device required
16 Device or resource busy
17 File exists
18 Invalid cross-device link
19 No such device
20 Not a directory
21 Is a directory
22 Invalid argument
23 Too many open files in system
24 Too many open files
25 Inappropriate ioctl for device
26 Text file busy
27 File too large
28 No space left on device
29 Illegal seek
30 Read-only file system
31 Too many links
32 Broken pipe
33 Numerical argument out of domain
34 Numerical result out of range
35 Resource deadlock avoided
36 File name too long
37 No locks available
38 Function not implemented
39 Directory not empty
40 Too many levels of symbolic links
41 Unknown error 41
42 No message of desired type
43 Identifier removed
44 Channel number out of range
45 Level 2 not synchronized
46 Level 3 halted
47 Level 3 reset
48 Link number out of range
49 Protocol driver not attached
50 No CSI structure available
51 Level 2 halted
52 Invalid exchange
53 Invalid request descriptor
54 Exchange full
55 No anode
56 Invalid request code
57 Invalid slot
58 Unknown error 58
59 Bad font file format
60 Device not a stream
61 No data available
62 Timer expired
63 Out of streams resources
64 Machine is not on the network
65 Package not installed
66 Object is remote
67 Link has been severed
68 Advertise error
69 Srmount error
70 Communication error on send
71 Protocol error
72 Multihop attempted
73 RFS specific error
74 Bad message
75 Value too large for defined data type
76 Name not unique on network
77 File descriptor in bad state
78 Remote address changed
79 Can not access a needed shared library
80 Accessing a corrupted shared library
81 .lib section in a.out corrupted
82 Attempting to link in too many shared libraries
83 Cannot exec a shared library directly
84 Invalid or incomplete multibyte or wide character
85 Interrupted system call should be restarted
86 Streams pipe error
87 Too many users
88 Socket operation on non-socket
89 Destination address required
90 Message too long
91 Protocol wrong type for socket
92 Protocol not available
93 Protocol not supported
94 Socket type not supported
95 Operation not supported
96 Protocol family not supported
97 Address family not supported by protocol
98 Address already in use
99 Cannot assign requested address
100 Network is down
101 Network is unreachable
102 Network dropped connection on reset
103 Software caused connection abort
104 Connection reset by peer
105 No buffer space available
106 Transport endpoint is already connected
107 Transport endpoint is not connected
108 Cannot send after transport endpoint shutdown
109 Too many references: cannot splice
110 Connection timed out
111 Connection refused
112 Host is down
113 No route to host
114 Operation already in progress
115 Operation now in progress
116 Stale NFS file handle
117 Structure needs cleaning
118 Not a XENIX named type file
119 No XENIX semaphores available
120 Is a named type file
121 Remote I/O error
122 Disk quota exceeded
123 No medium found
124 Wrong medium type
125 Operation canceled
126 Required key not available
127 Key has expired
128 Key has been revoked
129 Key was rejected by service
130 Owner died
131 State not recoverable
132~ Unknown error
2017-06-26 18:45:17 whuzm08 阅读数 527

一 errno出现的原因

由于一般的函数返回值只会返回执行成功与否,根据返回值并不能得到出错的真正原因,还有一种情况是返回值可以返回任何值,比如-1也是合法的,这时errno就出现了,记录具体的错误原因。它由libc定义:

int errno = 0;

是一个int类型的变量。


二 常见的使用误区

  • 根据errno来判断执行是否成功
errno是用来记录错误的,所以函数执行成功并不会修改errno的值,errno在程序启动时被初始化为0,任何库函数都不会设置errno为0,在函数执行出错时才会设置errno,如果根据errno来判断函数执行成功与否显然是不行的,因为你不知是前一个函数没执行成功还是前前一个函数没执行成功,除非在调用函数之前手动设置errno为0

  • errno判断位置不对
if (somecall() == -1) {
printf("somecall() failed\n");
if (errno == ...) { ... }
}
这样的例子并不能得到somecall这个函数的运行所产生的错误代码,因为很可能是printf这个函数产生的。正确的做法是errno的判断应该紧随函数调用之后。

  • errno线程安全问题
在多线程编程应用中,一定要注意libc是否支持线程TLS,如果不是,则使用errno就会出现问题,举例说明:

if (somecall() == -1) {
if (errno == ...) { ... }
}
如果是多线程的,可能执行完somecall() 后刚好进程切换,切换到同应用中的其他线程,其他线程可能调用库函数修改了errno,如果errno又不是线程局部变量,这时再切换到本线程执行,结果显然是不正确的。

  • 哪些函数会设置errno?
并不是所有的函数出错后都会设置errno,libc中好像是这样的,对于其他的开源库,可能根本没有使用到errno。


基于上述原因,个人认为errno并不是一种很好的存在,使用时一定要非常谨慎。

2019-03-31 10:15:35 qq_41453285 阅读数 78

一、errno全局变量

  • 概念:只要有一个函数中有错误发生,全局变量errno就被设置为一个指明该错误类型的正值

特点:

  • 头文件:#include<errno.h>
  • errno的值只在函数发生错误时设置。如果函数不返回错误,errno的值就没有定义
  • errno的错误值都是整型常量,这些常量以'E'开头开头,定义在头文件<errno.h>中
  • errno的值对应着不同的错误信息,可以手动修改
  • 不存在errno为0的错误

二、打印错误信息函数

#inlcude<string.h>
char *strerror(int ernum);
  • strerror将errno变量的值变为一个出错消息字符串,并返回这个字符串的指针
#include<stdio.h>
void perror(const char *msg);
  • perror打印错误信息
  • 信息格式:先输出msg,然后跟一个冒号、一个空格,接着加上errno错误的信息,最后加上换行符

三、演示案例

#include<errno.h>
#include<string.h>
#include<stdio.h>
int
main(int argc,char *argv[])
{
    fprintf(stderr,"EACCES:%s\n",strerror(EACCES));
    errno=ENOENT;
    perror(argv[0]);
    exit(0);
}
//EACCES和ENOENT都是errno的值

 

2016-10-16 21:07:16 chwzmx123 阅读数 311

(1)errno(error number),Linux系统对各种常见的错误做了个编号,当函数执行错误时,函数会返回一个特定的errno编号(int 类型)来告诉我们这个函数哪里错了。
(2)errno是由OS来维护的一个全局变量,任何OS内部函数都可以通过设置errno来告诉上层调用者究竟刚才发生了一个什么错误。
(3)Linux系统提供了一个函数perror(print errot),perror函数内部会读取errno并且将这个数字转成对应的错误字符串,然后打印出来;

Unix errno值

阅读数 731

没有更多推荐了,返回首页