2009-02-02 14 views

risposta

263

È possibile utilizzare strerror() per ottenere una stringa leggibile dall'uomo per il numero di errore. Questa è la stessa stringa stampata da perror() ma è utile se si sta formattando il messaggio di errore per qualcosa di diverso dall'output di errore standard.

Ad esempio:

#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 supporta anche la variante in modo esplicito-threadsafe strerror_r().

+21

Si consiglia di evitare strerror_r perché: 1) lo strerror è garantito reentrant (thread-safe) in POSIX comunque 2) versione POSIX e GNU di strerror_r sono diversi 3) un'implementazione dovrebbe essere danneggiata al cervello per avere uno strerror che ha scritto sul proprio buffer statico. – Chris

+4

1. NON è garantito un reentrant o thread safe 3. La maggior parte delle implementazioni DO scrive sul buffer statico interno, inclusa l'implementazione GNU LibC – Ivan

+0

@Ivan è corretto e @Chris non è corretto. 'strerror()' non è thread-safe mentre 'strerror_r()' è thread-safe. Le funzioni MT-Safe o Thread-Safe sono sicure per chiamare in presenza di altri thread. MT, in MT-Safe, sta per Multi Thread. _-p26, Libreria GNU C_ 'char * strerror (int errnum)' [Funzione] Preliminary: | MT: corsa pericolosa: strerror | Heap AS-Unsafe i18n | AC-Unsafe mem | Vedere Sezione 1.2.2.1 [Concetti di sicurezza POSIX], pagina 2. _-p58, Libreria GNU C_ – jargonjunkie

0

Significa:

file o la directory non trovato.

5

Qui è . Questo dovrebbe dirti cosa significa e cosa fare con loro. Evitare di usare il valore numerico e utilizzare le costanti elencate qui, poiché il numero può cambiare tra sistemi diversi.

+2

Odio come la documentazione di unix non associ costante al valore intero. Quale valore è "EIO"? I documenti sono inutili come questo. –

+4

@SomeoneSomewhere Questa è una funzionalità, non un bug. Dovresti sempre usare le costanti del codice di errore simbolico nel codice, non i numeri letterali. Questo rende il tuo codice molto più leggibile, perché qualcosa come EQFULL è molto più significativo di 106. Purtroppo, il linguaggio non impone questo, quindi ottieni persone che sono pigre o incasinate nella testa che scrivono 106 invece di EQFULL. Sentiti libero di inviare a quelle persone un bel peer che picchia. – allyourcode

+3

Il problema è che perror non ti dice a quale macro equivalente l'errore si riferisce, esso stampa un altro messaggio di errore completamente non correlato che metà della volta non appare nemmeno nella pagina man. Voglio un perror() che stampi il nome MACRO in modo da poter cercare l'errore insanguinato nella pagina man! – DarwinSurvivor

2

chiamata

perror("execl"); 

in caso di errore.

Esempio:

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

Le pagine man di errno(3) e perror(3) sono interessanti, anche ...

19

Codice di errore 2 significa "file/directory non trovata". In generale, è possibile utilizzare la funzione perror per stampare una stringa leggibile dall'uomo.

47

Invece di correre perror su qualsiasi codice di errore che si ottiene, è possibile recuperare un elenco completo dei errno valori sul sistema con il seguente one-liner:

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

+3

Per riferimento, ecco un elenco da Ubuntu 14.04 amd64 http://pastebin.com/407gDBPq – kevinf

0

Quando si utilizza strace (su Linux) per eseguire il tuo binario, emetterà i ritorni dalle chiamate di sistema e il significato del numero di errore. Questo a volte può essere utile a te.

6

Ci sono alcune funzioni utili per gestire errno s. (Giusto per chiarire, questi sono incorporati a libc - sto solo fornendo implementazioni di esempio perché alcune persone trovano la lettura del codice più chiaro che leggere inglese.)

#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 restituisce una stringa che descrive il numero di errore ci sei passato. Attenzione, questo non è sicuro da thread o da interrupt; è libero di riscrivere la stringa e restituire lo stesso puntatore al prossimo richiamo. Usa strerror_r se devi preoccuparti di questo.

#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 stampa il messaggio si dà, più una stringa che descrive l'attuale errno, per errore standard.

+2

'alcune persone trovano il codice di lettura più chiaro della lettura della verità inglese. – Qix

3

Io uso il seguente script:

#!/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

Su Linux v'è anche uno strumento molto accurato in grado di dire subito che cosa significa ogni codice di errore. Su Ubuntu: apt-get install errno.

Quindi se per esempio si desidera ottenere la descrizione del tipo di errore 2, basta digitare errno 2 nel terminale.

Con errno -l si ottiene una lista con tutti gli errori e le loro descrizioni. Molto più semplice di altri metodi menzionati dai precedenti poster.

+14

Oggigiorno parte del pacchetto moreutils (http://joeyh.name/code/moreutils/) – janneb

+0

+ janneb yes, tuttavia il nome del pacchetto errno è ancora completamente valido. – 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); 
}  

Opere su Solaris.
cc perror.c -o perror < < utilizzare questa linea per compilarlo

+1

Utilizzando cc? Woaahhh man, tu dal futuro? – carefulnow1

0

Ho la seguente funzione nel mio file .bashrc - sembra il valore errno dai file di intestazione (può essere sia /usr/include/errno.h, /usr/include/linux/errno.h, ecc, ecc)

funziona se i file di intestazione vengono installati sulla macchina ;-)

di solito il file di intestazione hanno un errore di + Segue la spiegazione nel commento; qualcosa di quanto segue:

./asm-generic/errno-base.h:#define EAGAIN 11/* Riprovare */

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

Questo è più veloce di guardare il codice errno.h, più breve rispetto maggior parte delle soluzioni postato qui e non richiede l'installazione di strumenti di terze parti:

perl -E 'say $!=shift' 2

cede

No such file or directory

+0

Whoohoo. Veloce, non si basa su una ricompilazione e funziona (quasi) ovunque, anche sulla vecchia macchina dove errno.h non è disponibile. Molte grazie. –

12

Ecco l'output errno -l riformattato in un formato leggibile:

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 

ho usato tabularise in Vim per allineare le colonne:

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

Tipo sudo apt-get install errno e poi una volta che è installato, tipo errno -l per tutti i numeri di errore. Puoi anche vedere solo quelli del file eseguendo il piping a grep, ad esempio: errno | grep file.