2009-02-02 8 views

Antwort

263

Sie können strerror() verwenden, um eine lesbare Zeichenfolge für die Fehlernummer zu erhalten. Dies ist die gleiche Zeichenfolge, die von perror() gedruckt wird, aber es ist nützlich, wenn Sie die Fehlermeldung für etwas anderes als Standardfehlerausgabe formatieren.

Zum Beispiel:

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

/* ... */ 

if(read(fd, buf, 1)==-1) { 
    printf("Oh dear, something went wrong with read()! %s\n", strerror(errno)); 
} 

Linux unterstützt auch die explizit THREAD Variante strerror_r().

+21

Ich würde empfehlen, strerror_r zu vermeiden, weil: 1) streerror in POSIX sowieso reentrant (Thread-sicher) ist 2) POSIX und GNU-Version von strerror_r sind unterschiedlich 3) eine Implementierung müsste hirngeschädigt sein, um einen Strehler zu haben, der in seinen eigenen statischen Puffer geschrieben hat. – Chris

+4

1. Es ist NICHT garantiert, Reentrant oder Threadsafe 3. Die meisten Implementierungen schreiben in internen statischen Puffer, einschließlich GNU LibC Implementierung – Ivan

+0

@ Ivan ist korrekt und @ Chris falsch. 'strerror()' ist nicht threadsicher, während 'strerror_r()' threadsicher ist. MT-Safe- oder Thread-Safe-Funktionen können bei Vorhandensein anderer Threads sicher aufgerufen werden. MT, in MT-Safe, steht für Multi Thread. _-p26, Die GNU C-Bibliothek_ 'char * strerror (int errnum)' [Funktion] Vorläufig: | MT-Unsafe Rennen: Strehler | AS-Unsichere Heap i18n | AC-Unsicher mem | Siehe Abschnitt 1.2.2.1 [POSIX-Sicherheitskonzepte], Seite 2. _-p58, Die GNU C-Bibliothek_ – jargonjunkie

0

Es bedeutet:

Datei oder Verzeichnis nicht gefunden.

5

Hier ist . Das sollte dir sagen, was es bedeutet und was damit zu tun ist. Sie sollten es vermeiden, den numerischen Wert zu verwenden und die dort aufgeführten Konstanten zu verwenden, da sich die Anzahl zwischen verschiedenen Systemen ändern kann.

+2

Ich hasse, wie die Unix-Dokumentation keine Konstante mit einem ganzzahligen Wert verbindet. Welchen Wert hat "EIO"? Docs sind so wertlos. –

+4

@SomeoneSomewhere Das ist eine Funktion, kein Bug. Sie sollten immer symbolische Fehlercode-Konstanten in Ihrem Code verwenden, nicht Nummernliterale. Dies macht Ihren Code viel lesbarer, weil etwas wie EQFULL viel aussagekräftiger ist als 106. Leider erzwingt die Sprache dies nicht, so dass Sie Leute bekommen, die faul oder verwirrt sind und 106 statt EQFULL schreiben. Fühlen Sie sich frei, diesen Leuten einen netten Gleichen zu schicken. – allyourcode

+3

Das Problem ist, dass perror Ihnen nicht mitteilt, auf welches Makroäquivalent sich der Fehler bezieht, es gibt eine andere Fehlermeldung aus, die völlig unabhängig davon ist, dass die Hälfte der Zeit nicht einmal in der Manpage erscheint. Ich möchte eine perror(), die den MACRO-Namen druckt, so dass ich den blutigen Fehler in der Manpage nachschlagen kann! – DarwinSurvivor

2

Anruf

perror("execl"); 

im Fehlerfall.

Probe:

if(read(fd, buf, 1)==-1) { 
    perror("read"); 
} 

Die manpages von errno(3) und perror(3) interessant sind auch ...

19

Fehlercode 2 bedeutet "Datei/Verzeichnis nicht gefunden". Im Allgemeinen können Sie die Funktion perror verwenden, um eine lesbare Zeichenfolge zu drucken.

47

Statt perror auf jedem Fehlercode ausgeführt werden Sie erhalten, können Sie eine vollständige Liste der errno Werte auf Ihrem System mit dem folgenden Einzeiler abrufen:

cpp -dM /usr/include/errno.h | grep 'define E' | sort -n -k 3

+3

Hier ist eine Liste von Ubuntu 14.04 amd64 http://pastebin.com/407gDBPq – kevinf

0

Wenn Sie strace verwenden (auf Linux) um Ihre Binärdatei auszuführen, gibt es die Rückmeldungen von Systemaufrufen aus und was die Fehlernummer bedeutet. Dies kann Ihnen manchmal nützlich sein.

6

Es gibt ein paar nützliche Funktionen für den Umgang mit errno s. (Nur um deutlich zu machen, werden diese eingebaut, um libc - Ich bin die Bereitstellung nur Implementierungen Probe, weil einige Leute klare Lesen Code als Englisch zu lesen.)

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

/* you can think of it as being implemented like this: */ 
static char strerror_buf[1024]; 
const char *sys_errlist[] = { 
    [EPERM] = "Operation not permitted", 
    [ENOENT] = "No such file or directory", 
    [ESRCH] = "No such process", 
    [EINTR] = "Interrupted system call", 
    [EIO] = "I/O error", 
    [ENXIO] = "No such device or address", 
    [E2BIG] = "Argument list too long", 
    /* etc. */ 
}; 
int sys_nerr = sizeof(sys_errlist)/sizeof(char *); 
char *strerror(int errnum) { 
    if (0 <= errnum && errnum < sys_nerr && sys_errlist[errnum]) 
     strcpy(strerror_buf, sys_errlist[errnum]); 
    else 
     sprintf(strerror_buf, "Unknown error %d", errnum); 
    return strerror_buf; 
} 

strerror gibt einen String beschreibt die Fehlernummer Du bist dazu gekommen. Achtung, dies ist nicht Thread- oder Interrupt-sicher; Es ist frei, die Zeichenfolge neu zu schreiben und den gleichen Zeiger auf den nächsten Aufruf zurückzugeben. Verwenden Sie strerror_r, wenn Sie sich darum kümmern müssen.

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

/* you can think of it as being implemented like this: */ 
void perror(const char *s) { 
    fprintf(stderr, "%s: %s\n", s, strerror(errno)); 
} 

perror druckt die Nachricht, die Sie geben, sowie eine Zeichenfolge zur Beschreibung des aktuellen errno, auf Standardfehler.

+2

'Manche Menschen finden den Lesecode klarer als das Lesen der englischen Wahrheit. – Qix

3

Ich benutze das folgende Skript:

#!/usr/bin/python 

import errno 
import os 
import sys 

toname = dict((str(getattr(errno, x)), x) 
       for x in dir(errno) 
       if x.startswith("E")) 
tocode = dict((x, getattr(errno, x)) 
       for x in dir(errno) 
       if x.startswith("E")) 

for arg in sys.argv[1:]: 
    if arg in tocode: 
     print arg, tocode[arg], os.strerror(tocode[arg]) 
    elif arg in toname: 
     print toname[arg], arg, os.strerror(int(arg)) 
    else: 
     print "Unknown:", arg 
39

Unter Linux gibt es auch ein sehr nützliches Werkzeug, das sofort sagen kann, was jeder Fehlercode bedeutet. Auf Ubuntu: apt-get install errno.

Wenn Sie zum Beispiel die Beschreibung des Fehlertyps 2 erhalten möchten, geben Sie einfach errno 2 in das Terminal ein.

Mit errno -l erhalten Sie eine Liste mit allen Fehlern und deren Beschreibungen. Viel einfacher als andere Methoden, die von früheren Postern erwähnt wurden.

+14

Heutzutage Teil des moreutils Pakets (http://joehy.name/code/moreutils/) – janneb

+0

+ janneb ja, jedoch ist der errno Paketname immer noch vollständig gültig. – carefulnow1

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

int main(int i, char *c[]) { 
    if (i != 2) 
    fprintf(stderr, "Usage: perror errno\n"); 
    else { 
    errno = atoi(c[1]); 
    perror(""); 
    } 
    exit(0); 
}  

Funktioniert auf Solaris.
cc perror.c -o perror < < verwendet diese Zeile zu kompilieren

+1

Verwenden von cc? Woaahhh Mann, du aus der Zukunft? – carefulnow1

0

Ich habe die folgende Funktion in meinem .bashrc - den errno-Wert aus den Header-Dateien sucht (kann entweder /usr/include/errno.h, /usr/include/linux/errno.h usw. sein, etc.)

Es funktioniert, wenn die Header-Dateien auf dem Rechner installiert sind ;-)

Normalerweise sind die Header-Datei ein Fehler + neben der Erklärung der Kommentar kommt; etwas von den folgenden:

./asm-generic/errno-base.h:#define EAGAIN 11/* Versuchen Sie es erneut */

function errno() 
{ 
    local arg=$1 

    if [[ "x$arg" == "x-h" ]]; then 
     cat <<EOF 
     Usage: errno <num> 
     Prints text that describes errno error number 
     EOF 
    else 
     pushd /usr/include 
     find . -name "errno*.h" | xargs grep "[[:space:]]${arg}[[:space:]]" 
     popd 
    fi 
} 
5

Dies ist schneller als Sie den Code in errno.h aufzublicken, kürzer als die meisten Lösungen hier gepostet und es nicht die Installation von Tools von Drittanbietern erfordern:

perl -E 'say $!=shift' 2

012 ergibt Hier

+0

Whoohoo. Schnell, ist nicht auf eine Neukompilierung angewiesen und funktioniert (fast) überall, auch auf alten Rechnern, auf denen errno.h nicht verfügbar ist. Danke vielmals. –

12

ist die Ausgabe von errno -l zur besseren Lesbarkeit umformatiert:

1 EPERM    Operation not permitted 
    2 ENOENT   No such file or directory 
    3 ESRCH    No such process 
    4 EINTR    Interrupted system call 
    5 EIO    Input/output error 
    6 ENXIO    No such device or address 
    7 E2BIG    Argument list too long 
    8 ENOEXEC   Exec format error 
    9 EBADF    Bad file descriptor 
10 ECHILD   No child processes 
11 EAGAIN   Resource temporarily unavailable 
11 EWOULDBLOCK  Resource temporarily unavailable 
12 ENOMEM   Cannot allocate memory 
13 EACCES   Permission denied 
14 EFAULT   Bad address 
15 ENOTBLK   Block device required 
16 EBUSY    Device or resource busy 
17 EEXIST   File exists 
18 EXDEV    Invalid cross-device link 
19 ENODEV   No such device 
20 ENOTDIR   Not a directory 
21 EISDIR   Is a directory 
22 EINVAL   Invalid argument 
23 ENFILE   Too many open files in system 
24 EMFILE   Too many open files 
25 ENOTTY   Inappropriate ioctl for device 
26 ETXTBSY   Text file busy 
27 EFBIG    File too large 
28 ENOSPC   No space left on device 
29 ESPIPE   Illegal seek 
30 EROFS    Read-only file system 
31 EMLINK   Too many links 
32 EPIPE    Broken pipe 
33 EDOM    Numerical argument out of domain 
34 ERANGE   Numerical result out of range 
35 EDEADLK   Resource deadlock avoided 
35 EDEADLOCK   Resource deadlock avoided 
36 ENAMETOOLONG  File name too long 
37 ENOLCK   No locks available 
38 ENOSYS   Function not implemented 
39 ENOTEMPTY   Directory not empty 
40 ELOOP    Too many levels of symbolic links 
42 ENOMSG   No message of desired type 
43 EIDRM    Identifier removed 
44 ECHRNG   Channel number out of range 
45 EL2NSYNC   Level 2 not synchronized 
46 EL3HLT   Level 3 halted 
47 EL3RST   Level 3 reset 
48 ELNRNG   Link number out of range 
49 EUNATCH   Protocol driver not attached 
50 ENOCSI   No CSI structure available 
51 EL2HLT   Level 2 halted 
52 EBADE    Invalid exchange 
53 EBADR    Invalid request descriptor 
54 EXFULL   Exchange full 
55 ENOANO   No anode 
56 EBADRQC   Invalid request code 
57 EBADSLT   Invalid slot 
59 EBFONT   Bad font file format 
60 ENOSTR   Device not a stream 
61 ENODATA   No data available 
62 ETIME    Timer expired 
63 ENOSR    Out of streams resources 
64 ENONET   Machine is not on the network 
65 ENOPKG   Package not installed 
66 EREMOTE   Object is remote 
67 ENOLINK   Link has been severed 
68 EADV    Advertise error 
69 ESRMNT   Srmount error 
70 ECOMM    Communication error on send 
71 EPROTO   Protocol error 
72 EMULTIHOP   Multihop attempted 
73 EDOTDOT   RFS specific error 
74 EBADMSG   Bad message 
75 EOVERFLOW   Value too large for defined data type 
76 ENOTUNIQ   Name not unique on network 
77 EBADFD   File descriptor in bad state 
78 EREMCHG   Remote address changed 
79 ELIBACC   Can not access a needed shared library 
80 ELIBBAD   Accessing a corrupted shared library 
81 ELIBSCN   .lib section in a.out corrupted 
82 ELIBMAX   Attempting to link in too many shared libraries 
83 ELIBEXEC   Cannot exec a shared library directly 
84 EILSEQ   Invalid or incomplete multibyte or wide character 
85 ERESTART   Interrupted system call should be restarted 
86 ESTRPIPE   Streams pipe error 
87 EUSERS   Too many users 
88 ENOTSOCK   Socket operation on non-socket 
89 EDESTADDRREQ  Destination address required 
90 EMSGSIZE   Message too long 
91 EPROTOTYPE  Protocol wrong type for socket 
92 ENOPROTOOPT  Protocol not available 
93 EPROTONOSUPPORT Protocol not supported 
94 ESOCKTNOSUPPORT Socket type not supported 
95 ENOTSUP   Operation not supported 
95 EOPNOTSUPP  Operation not supported 
96 EPFNOSUPPORT  Protocol family not supported 
97 EAFNOSUPPORT  Address family not supported by protocol 
98 EADDRINUSE  Address already in use 
99 EADDRNOTAVAIL  Cannot assign requested address 
100 ENETDOWN   Network is down 
101 ENETUNREACH  Network is unreachable 
102 ENETRESET   Network dropped connection on reset 
103 ECONNABORTED  Software caused connection abort 
104 ECONNRESET  Connection reset by peer 
105 ENOBUFS   No buffer space available 
106 EISCONN   Transport endpoint is already connected 
107 ENOTCONN   Transport endpoint is not connected 
108 ESHUTDOWN   Cannot send after transport endpoint shutdown 
109 ETOOMANYREFS  Too many references: cannot splice 
110 ETIMEDOUT   Connection timed out 
111 ECONNREFUSED  Connection refused 
112 EHOSTDOWN   Host is down 
113 EHOSTUNREACH  No route to host 
114 EALREADY   Operation already in progress 
115 EINPROGRESS  Operation now in progress 
116 ESTALE   Stale file handle 
117 EUCLEAN   Structure needs cleaning 
118 ENOTNAM   Not a XENIX named type file 
119 ENAVAIL   No XENIX semaphores available 
120 EISNAM   Is a named type file 
121 EREMOTEIO   Remote I/O error 
122 EDQUOT   Disk quota exceeded 
123 ENOMEDIUM   No medium found 
124 EMEDIUMTYPE  Wrong medium type 
125 ECANCELED   Operation canceled 
126 ENOKEY   Required key not available 
127 EKEYEXPIRED  Key has expired 
128 EKEYREVOKED  Key has been revoked 
129 EKEYREJECTED  Key was rejected by service 
130 EOWNERDEAD  Owner died 
131 ENOTRECOVERABLE State not recoverable 
132 ERFKILL   Operation not possible due to RF-kill 
133 EHWPOISON   Memory page has hardware error 

Ich benutzte tabularise in Vim, um die Spalten ausrichten:

:%Tab /^[^ ]*\zs /r1l1l1 
:%Tab /^ *[^ ]* *[^ ]*\zs /l1 
0

Typ sudo apt-get install errno und dann einmal, dass installiert ist, geben Sie errno -l für alle Fehlernummern. Sie können auch nur die Datei anzeigen, indem Sie sie an grep senden, so: errno | grep file.