2009-02-02 23 views

Respuesta

263

Puede usar strerror() para obtener una cadena legible para el número de error. Esta es la misma cadena impresa por perror(), pero es útil si está formateando el mensaje de error para algo distinto a la salida de error estándar.

Por ejemplo:

#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 también soporta la variante explícitamente-threadsafe strerror_r().

+21

Recomendaría evitar strerror_r porque: 1) strerror está garantizado reentrante (seguro para subprocesos) en POSIX de todos modos 2) Versión POSIX y GNU de strerror_r son diferentes 3) una implementación tendría que sufrir daño cerebral para tener un strerror que escribiera en su propio buffer estático. – Chris

+4

1. NO se garantiza que sea reentrante o que sea seguro para subprocesos 3. La mayoría de las implementaciones escriben en el búfer estático interno, incluida la implementación de GNC LibC – Ivan

+0

@Ivan es correcto y @Chris es incorrecto. 'strerror()' no es seguro para subprocesos, mientras que 'strerror_r()' es seguro para subprocesos. Las funciones MT-Safe o Thread-Safe son seguras para llamar en presencia de otros hilos. MT, en MT-Safe, significa Multi Thread. _-p26, La Biblioteca GNU C_ 'char * strerror (int errnum)' [Función] Preliminary: | Carrera MT-insegura: strerror | AS-inseguro montón i18n | AC-Mem inseguro | Vea la Sección 1.2.2.1 [Conceptos de seguridad POSIX], página 2. _-p58, La biblioteca GNU C_ – jargonjunkie

0

Significa:

archivo o directorio no encontrado.

5

Aquí está . Eso debería decirle lo que significa y qué hacer con ellos. Debe evitar usar el valor numérico y usar las constantes que figuran allí también, ya que el número puede cambiar entre diferentes sistemas.

+2

Odio cómo la documentación de UNIX no asocia constante al valor entero. ¿Qué valor es "EIO"? Los documentos no tienen valor así. –

+4

@SomeoneSomewhere Esa es una característica, no un error. Siempre debe usar constantes de código de error simbólico en su código, no literales numéricos. Esto hace que tu código sea mucho más legible, porque algo como EQFULL es mucho más significativo que 106. Tristemente, el lenguaje no hace cumplir esto, por lo que obtienes a personas que son perezosas o tienen problemas en la cabeza que escriben 106 en lugar de EQFULL. Siéntase libre de enviar a esas personas una buena peer peer. – allyourcode

+3

El problema es que Perror no le dice a qué macro equivalente se refiere el error, sino que imprime otro mensaje de error completamente no relacionado que la mitad del tiempo ni siquiera aparece en la página de manual. Quiero un perror() que imprime el nombre MACRO para que pueda buscar el error sangriento en la página de manual. – DarwinSurvivor

2

llamada

perror("execl"); 

en caso de error.

muestra:

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

Las páginas de manual de errno(3)perror(3) y son interesantes, también ...

19

código de error 2 significa "archivo/directorio no encontrado". En general, puede usar la función perror para imprimir una cadena legible por humanos.

47

En lugar de correr perror en cualquier código de error que se obtiene, se puede recuperar una lista completa de errno valores en el sistema con el siguiente de una sola línea:

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

+3

Como referencia, aquí hay una lista de Ubuntu 14.04 amd64 http://pastebin.com/407gDBPq – kevinf

0

Cuando se utiliza strace (en Linux) para ejecutar su binario, generará los retornos de las llamadas al sistema y lo que significa el número de error. Esto a veces puede ser útil para usted.

6

Hay algunas funciones útiles para tratar con errno s. (Sólo para que quede claro, éstos son incorporados a libc - Sólo estoy proporcionar implementaciones de muestra debido a que algunas personas encuentran la lectura de códigos más claro que la lectura de Inglés.)

#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 devuelve una cadena que describe el número de error lo has pasado. Precaución, esto no es seguro para hilos o interrupciones; es libre de reescribir la cadena y devolver el mismo puntero en la siguiente invocación. Use strerror_r si necesita preocuparse por eso.

#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 imprime el mensaje que le des, más una cadena que describe la corriente errno, al error estándar.

+2

'algunas personas encuentran que leer el código es más claro que leer la verdad en inglés. – Qix

3

que utilizar el siguiente 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

En Linux hay también una herramienta muy eficiente que puede saber de inmediato lo que significa cada código de error. En Ubuntu: apt-get install errno.

Luego, si, por ejemplo, desea obtener la descripción del tipo de error 2, simplemente escriba errno 2 en el terminal. Con errno -l obtendrá una lista con todos los errores y sus descripciones. Mucho más fácil que otros métodos mencionados en los carteles anteriores.

+14

Actualmente parte del paquete moreutils (http://joeyh.name/code/moreutils/) – janneb

+0

+ janneb sí, sin embargo, el nombre del paquete errno sigue siendo completamente válido. – 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); 
}  

Funciona en Solaris.
cc perror.c -o perror < < uso de esta línea para compilarlo

+1

¿Cómo usar cc? Woaahhh hombre, ¿tú del futuro? – carefulnow1

0

que tiene la función siguiente en mi archivo .bashrc - se ve el valor errno a partir de los archivos de cabecera (puede ser /usr/include/errno.h, /usr/include/linux/errno.h, etc., etc.)

funciona si los archivos de cabecera están instalados en la máquina ;-)

por lo general, el archivo de cabecera tienen un error + Luego viene la explicación en el comentario; algo de lo siguiente:

./asm-generic/errno-base.h:#define EAGAIN 11/* Inténtelo de nuevo */

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

Esto es más rápido que buscar el código en errno.h, más corto que la mayoría de las soluciones publicadas aquí y no requiere la instalación de herramientas de terceros:

perl -E 'say $!=shift' 2

produce

No such file or directory

+0

Whoohoo. Rápido, no depende de una recompilación, y funciona (casi) en todas partes, incluso en una máquina antigua donde errno.h no está disponible. Muchas gracias. –

12

Aquí está la salida de errno -l reformateado para mejorar la legibilidad:

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 

Solía ​​tabularise en Vim para alinear las columnas:

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

Tipo sudo apt-get install errno y luego una vez que se ha instalado, el tipo errno -l para todos los números de error También puede ver solo los archivos al canalizarlo a grep, de esta manera: errno | grep file.