C语言 如何检查errno的值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46013418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check the value of errno?
提问by Hana
I am using a system call and in case it fails, I need to do different things for different errnos.
我正在使用系统调用,如果它失败,我需要为不同的 errnos 做不同的事情。
I need to write code that looks something like this:
我需要编写如下所示的代码:
int res;
res = systemCall();
if (res == -1)
{
if (errno == ENOMSG)
{
doSomething();
}
else
{
doSomethingElse();
}
}
perror doesn't help, because it only prints the value.
perror 没有帮助,因为它只打印值。
As for strerro - if it is what I need, I am not suer how to use it, because hereit says that the actual string is not the same as the error. Quote from the man page: "(For example, if errnum is EINVAL, the returned description will be "Invalid argument")".
至于 strerro - 如果它是我需要的,我不知道如何使用它,因为这里它说实际字符串与错误不同。来自手册页的引用:“(例如,如果 errnum 是 EINVAL,则返回的描述将是“无效参数”)”。
I am using Linux. System calls: msgsend and msgrcv (https://linux.die.net/man/2/msgrcv). I am not sure what C libraries you are asking about.
我正在使用 Linux。系统调用:msgsend 和 msgrcv ( https://linux.die.net/man/2/msgrcv)。我不确定你问的是什么 C 库。
I see I didn't explain myself well.
我看到我没有很好地解释自己。
Is the statement if (errno == ENOMSG) valid? Is there such a variable errno? Basically my question is: What should go in the ifstatement in order to test the errno?
if (errno == ENOMSG) 语句是否有效?有这样的变量errno吗?基本上我的问题是:if为了测试errno ,语句中应该包含什么?
回答by Steve Summit
How to check the value of errno:
如何检查 的值errno:
- You will need to
#include <errno.h>. - Yes, you can definitely say things like
if(errno == ENOENT) { ... }, and that is the common and recommended way of doing it. - In general, do notuse
errnoto determine that an error has occurred. Check the return value of the function, and if the return value indicates an error, then checkerrnoto see what the error was. (More on this below.) errnolooks like a variable, but it actually isn't. This doesn't concern you as long as you just say things likeif(errno == ENOENT) { ... }. But you probably shouldn't try to do something likeint errno_ptr = &errno;.- You can use functions like
perror()andstrerror()to get human-readable error strings corresponding toerrnovalues. But, yes, the strings you get are generally things like "No such file or directory". There is no good way that I know of to convert the errno valueENOENTto the string"ENOENT".
- 你将需要
#include <errno.h>。 - 是的,您绝对可以这样说
if(errno == ENOENT) { ... },这是常见且推荐的做法。 - 在一般情况下,千万不能使用
errno,以确定发生了错误。检查函数的返回值,如果返回值指示错误,则检查errno错误是什么。(更多关于这个下面。) errno看起来像一个变量,但实际上不是。只要您说诸如if(errno == ENOENT) { ... }. 但是你可能不应该尝试做类似的事情int errno_ptr = &errno;。- 您可以使用像
perror()和strerror()这样的函数来获取与errno值对应的人类可读的错误字符串。但是,是的,您得到的字符串通常是“没有这样的文件或目录”之类的东西。我不知道将 errno 值ENOENT转换为 string 的好方法"ENOENT"。
To say a little more about #3. Sometimes it's tempting to say something like
多说一点关于#3。有时很想说类似的话
errno = 0;
printf("Hello, world!\n");
if(errno != 0) {
fprintf(stderr, "printf failed!\n");
}
But don't do that. Instead do
但不要那样做。而是做
errno = 0;
int retval = printf("Hello, world!\n");
if(retval < 0) {
fprintf(stderr, "printf failed!\n");
}
The reason is that, somewhere in the process of doing its job, printfmight have done something that resulted in an error, something that set errno, but printfmight have recovered from that error and gone on to complete successfully.
原因是,在执行其工作的过程中的某个地方,printf可能做了一些导致错误的事情,一些 set errno,但printf可能已经从该错误中恢复并继续成功完成。
There are a very few library functions that are guaranteed notto touch errno if there wasn't an error (I think one example might be atoi), but in general, this is something you have to be careful of.
有极少数库函数可以保证在没有错误的情况下不会触及 errno(我认为一个例子可能是atoi),但总的来说,这是您必须小心的事情。
To say a little more about #4. errnolooks like a variable, and more specifically, it looks like a global variable. But of course global variables are bad. But errnohas been around forever; there are tens of millions of lines of code that use it; it's still basically pretty convenient; it's too late to "fix" it. So, instead, if you peek behind the curtain, you'll find that most implementations do something like
多说一点关于#4。 errno看起来像一个变量,更具体地说,它看起来像一个全局变量。但是当然全局变量是不好的。但errno一直存在;有数千万行代码使用它;基本上还是很方便的;“修复”它为时已晚。所以,相反,如果你从幕后窥视,你会发现大多数实现都做类似的事情
extern int __errno_pointer;
#define errno (*__errno_pointer)
or
或者
extern int *__errno_pointer_function();
#define errno (*__errno_function())
In this way, they can arrange for errnoto work reasonably properly even in, say, multithreaded code.
通过这种方式,errno即使在多线程代码中,他们也可以安排合理地正常工作。
回答by Basile Starynkevitch
I assume you are using Linux, and I suppose that you don't directlyuse the system call, but some of the (simple) wrappers (from your C library) listed in syscalls(2). Notice that some weird system calls are not wrapped by the C library (a well known example of unwrapped system call would be sigreturn(2)which you probably should never use). Quite often the C library is GNU glibc, but it might be musl-libcetc. Notice also that kernel raw system calls have different calling conventionsthan ordinary C function (so in practice a libc wrapper is required, and is in charge of dealing with errno). Notice also that errno(3)is generally a macro (almost behaving as some variable).
我假设您使用的是 Linux,并且我假设您不直接使用系统调用,而是syscalls(2) 中列出的一些(简单)包装器(来自您的 C 库)。请注意,一些奇怪的系统调用没有被 C 库包装(一个众所周知的未包装系统调用的例子是sigreturn(2),你可能永远不应该使用它)。C 库通常是GNU glibc,但也可能是musl-libc等。 另请注意,内核原始系统调用与普通 C 函数具有不同的调用约定(因此实际上需要 libc 包装器,并负责处理errno)。还要注意errno(3)通常是一个宏(几乎表现为某个变量)。
The msgrcv(2)man page documents that errnocould be one of E2BIG, EACCES, EFAULT... ENOMSG, ENOSYS... (refer to that man page to get the list of all possible errors).
该msgrcv(2)该手册页的文件errno可能是一个E2BIG,EACCES,EFAULT... ENOMSG,ENOSYS...(指的是男人页面获得所有可能的错误列表)。
So you would code something like
所以你会编写类似的代码
ssize_t siz = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
if (siz<0) { // msgrcv failed and has set errno
if (errno == ENOMSG)
dosomething();
else if (errno == EAGAIN)
dosomethingelse();
/// etc
else {
syslog(LOG_DAEMON|LOG_ERR, "msgrcv failure with %s\n",
strerror(errno));
exit(EXIT_FAILURE);
};
};
Is the statement
if (errno == ENOMSG).... valid?
声明
if (errno == ENOMSG)....有效吗?
Yes it is; you want to test errnoonly after some system call failure (e.g. when siz<0).
是的; 您只想errno在某些系统调用失败后进行测试(例如 when siz<0)。
Is there such a variable
errno?
有这样的变量
errno吗?
Not any more. Please read carefully errno(3)documentation. You should not declare extern int errno;(this was possible in the 1980s, not in 21stcentury) but you should always#include <errno.h>and use errnoas if it was a variable, but it is almost always some macro (whose definition appears in /usr/include/bits/errno.hwhich is included by /usr/include/errno.h).
不再。请仔细阅读 errno(3)文档。你不应该声明extern int errno;(这是有可能在20世纪80年代,而不是在21日世纪),但你应该总是#include <errno.h>和使用errno,如果它是一个变量,但它几乎总是有一些宏(其定义出现在/usr/include/bits/errno.h其中被列入/usr/include/errno.h)。
BTW, SysV-style facilities tend to become obsolete and are not always available. I recommend using POSIX message queues facilities, read mq_overview(7).
顺便说一句,SysV 风格的设施往往会过时,并不总是可用。我建议使用 POSIX 消息队列工具,阅读mq_overview(7)。
You might want to read the freely downloadable Advanced Linux Programming(an old book; you can buy something better & newer) and/or all the man pages reachable from intro(2)& syscalls(2)& intro(3).
您可能想阅读可免费下载的Advanced Linux Programming(一本旧书;您可以购买更好和更新的东西)和/或可从intro(2)& syscalls(2)& intro(3) 获得的所有手册页。
回答by P__J__
Include errno.h
包括 errno.h
Some examples:
一些例子:
// Error codes
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
Your implementation may have more errno includes, like for example /usr/include/asm-generic/errno.h.
您的实现可能有更多的 errno 包含,例如/usr/include/asm-generic/errno.h.

