imprimir impresora directamente c gdb errno

imprimir directamente en la impresora javascript



¿Por qué no se puede imprimir el valor de errno? (5)

Estoy mirando el siguiente código en una publicación SO de "Baja calidad" para asegurarme de que la muestra funciona, y mi pregunta es ¿por qué no puedo imprimir el valor de errno?

#include <stdio.h> #include <stdlib.h> #include <errno.h> int main(){ FILE *fp; errno = 0; fp=fopen("Not_exist.txt","r"); if(fp == NULL && errno == ENOENT) perror("file not exist"); return 0; }

Esto es lo que sucede cuando intento imprimir el valor:

(gdb) p errno Cannot find thread-local variables on this target (gdb)

Puedo imprimir el valor de fp muy bien. Como es de esperar, su valor es 0x00 .

Miré /usr/include/errno.h y una gran cantidad de los otros archivos incluidos incluidos como parte de errno.h , y no puedo entender cómo se define errno. Cualquier sugerencia o ayuda sería apreciada. Solo tengo curiosidad por eso; nada está roto.

Gracias.


Como otros han dicho, errno no es una variable que gdb puede imprimir. Pero gdb puede evaluar funciones, y __errno_location() devuelve un puntero a `errno ''. Lo único que tenemos que hacer entonces, es llamar a la función y eliminar la referencia del restult:

(gdb) p *__errno_location()

Y eso es.


En mi instalación de Ubuntu, tengo la siguiente sección en bits/errno.h :

/* Function to get address of global `errno'' variable. */ extern int *__errno_location (void) __THROW __attribute__ ((__const__)); # if !defined _LIBC || defined _LIBC_REENTRANT /* When using threads, errno is a per-thread value. */ # define errno (*__errno_location ()) # endif

Dicho eso, errno no es necesariamente una variable. Por diversos motivos, es posible que desee tener una función que le devuelva el valor del error en lugar de un extern int simple. 1 Es por eso que no puede imprimir su valor usando GDB.

1 por supuesto, como se puede ver, la llamada a la función debería devolver el puntero a la variable real y la macro errno lo desreferenciaría.


La variable errno es una especie de pato extraño. Debido a que la mayoría de las bibliotecas de tiempo de ejecución de estos días admiten subprocesos, no puede haber una sola variable errno . Si hubiera, entonces dos hilos podrían hacer cosas al mismo tiempo que ambos establezcan el valor errno , y se produciría una gran confusión.

Las bibliotecas de tiempo de ejecución hacen varios trucos para evitar este problema. Por ejemplo, uno podría hacer algo como:

#define errno __get_errno()

donde las referencias a errno realmente llaman a la función interna __get_errno() , que devuelve el valor correcto del número de error para el hilo actual. La desventaja de este método es que evita la asignación a errno, como errno = 0; (que algún código podría hacer). Las bibliotecas de tiempo de ejecución generalmente elegirán un enfoque más sofisticado.

Algunas bibliotecas de tiempo de ejecución (como la que estás utilizando, supongo) pueden declarar un tipo especial de "variable local de hilo" que puede tener un valor diferente en cada hilo. Parece que su depurador en su sistema no puede mostrar ese tipo de variable.


errno estándar C exige que errno sea ​​una macro que se expande a un valor l modificable. En el caso más simple, puede expandirse al nombre de una variable declarada, pero para las implementaciones que necesitan distintos objetos errno para diferentes subprocesos, típicamente se define algo como esto:

#define errno (*__errno_location ())

gdb usualmente puede evaluar llamadas a funciones; por ejemplo, en mi sistema:

(gdb) p __errno_location() $1 = -134383968 (gdb) p errno Cannot find thread-local variables on this target

El primer valor impreso es el valor bajo de 32 bits del valor del puntero devuelto por __errno_location() . No conozco gdb lo suficiente como para explicar ese comportamiento, pero demuestra que puede ejecutar llamadas a funciones.

Como solución, puede modificar el código fuente para que guarde la dirección de errno , o su valor, en una variable que puede mostrar gdb:

(gdb) l 1 #include <errno.h> 2 #include <stdio.h> 3 int main(void) { 4 errno = 42; /* arbitrary value */ 5 const int *errno_ptr = &errno; 6 int errno_value = errno; 7 printf("%d %d %d/n", errno, errno_value, *errno_ptr); 8 } (gdb) b 8 Breakpoint 1 at 0x4005b6: file c.c, line 8. (gdb) r Starting program: /home/kst/c 42 42 42 Breakpoint 1, main () at c.c:8 8 } (gdb) p errno Cannot find thread-local variables on this target (gdb) p errno_value $1 = 42 (gdb) p *errno_ptr $2 = 42

El enfoque *errno_ptr tiene la ventaja de que solo tiene que asignarlo una vez, a menos que esté depurando un programa de subprocesos múltiples. En ese caso, el valor de &errno puede variar según el hilo en el que lo evalúe.

Esto es probablemente un error, o al menos una característica que falta, en gdb .

ACTUALIZAR El comentario de Kevin Cox sugiere una solución alternativa:

print *((int*(*)())__errno_location)()

Y con gcc 6.2 y gdb 7.11, print errno realmente funciona:

(gdb) l 1 #include <errno.h> 2 int main(void) { 3 errno = 42; 4 return 0; 5 } (gdb) b 4 Breakpoint 1 at 0x6bf: file c.c, line 4. (gdb) r Starting program: /home/kst/c Breakpoint 1, main () at c.c:4 4 return 0; (gdb) p errno $1 = 42 (gdb)


_CRTIMP int* __cdecl __MINGW_NOTHROW _errno(void); #define errno (*_errno())

Esto se usa para que solo pueda pasar la dirección de un veriable preferido que contendrá el valor de error real devuelto por la función de llamada.

Ej. Usted puede definir la función _errno () como abajo

unsigned int errorValue; int* _errno() { return (&errorValue); }

Ahora uso:

void MyFunc() { if(some condition failure) errno = 10; //Or any error value as per your design else { //Actual operation } }

Después de MyFunc() , errorValue contendrá el error.