¿Alguien puede explicar este comportamiento de gdb?
900 memset(&new_ckpt_info,'\0',sizeof(CKPT_INFO));
(gdb)
**903 prev_offset = cp_node->offset;**
(gdb)
**905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_** HDR),i_offset);
(gdb)
**903 prev_offset = cp_node->offset;**
(gdb)
**905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_ HDR),i_offset);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
913 found = cpnd_find_exact_ckptinfo(cb , &ckpt_info , bitmap_offset , &offset , &prev_offset);
(gdb)
916 if(!found)
(gdb) p found
$1 = <value optimized out>
(gdb) set found=0
Left operand of assignment is not an lvalue.
¿Por qué después de ejecutar la línea 903 vuelve a ejecutar lo mismo para 905 908 910?
Otra cosa es que found
es una bool
variable de tipo, entonces, ¿por qué se muestra value optimized out
? No puedo establecer el valor de found
también.
Esto parece ser una optimización del compilador (en este caso es -O2
); ¿Cómo puedo establecer el valor de found
?
Respuestas:
Para depurar código optimizado, aprenda lenguaje ensamblador / máquina.
Utilice el modo GDB TUI. Mi copia de GDB lo habilita cuando escribo el signo menos y Enter. Luego escriba Cx 2 (es decir, mantenga presionado Control y presione X, suelte ambos y luego presione 2). Eso lo pondrá en fuente dividida y pantalla de desmontaje. Luego use
stepi
ynexti
para mover una instrucción de máquina a la vez. Utilice Cx o para cambiar entre las ventanas TUI.Descargue un PDF sobre el lenguaje de máquina de su CPU y las convenciones de llamadas a funciones. Aprenderá rápidamente a reconocer lo que se está haciendo con los argumentos de función y los valores de retorno.
Puede mostrar el valor de un registro utilizando un comando GDB como
p $eax
fuente
Vuelva a compilar sin optimizaciones (-O0 en gcc).
fuente
Declarar encontrado como "volátil". Esto debería decirle al compilador que NO lo optimice.
volatile int found = 0;
fuente
El compilador comenzará a hacer cosas muy inteligentes con las optimizaciones activadas. El depurador mostrará el código saltando mucho hacia adelante y hacia atrás debido a la forma optimizada en que se almacenan las variables en los registros. Esta es probablemente la razón por la que no puede establecer su variable (o en algunos casos ver su valor), ya que se ha distribuido inteligentemente entre registros para la velocidad, en lugar de tener una ubicación de memoria directa a la que el depurador pueda acceder.
¿Compilar sin optimizaciones?
fuente
Por lo general, los valores booleanos que se utilizan en las ramas inmediatamente después de que se calculan así nunca se almacenan en las variables. En cambio, el compilador simplemente se ramifica directamente de los códigos de condición que se establecieron en la comparación anterior. Por ejemplo,
int a = SomeFunction(); bool result = --a >= 0; // use subtraction as example computation if ( result ) { foo(); } else { bar(); } return;
Por lo general, se compila en algo como:
call .SomeFunction ; calls to SomeFunction(), which stores its return value in eax sub eax, 1 ; subtract 1 from eax and store in eax, set S (sign) flag if result is negative jl ELSEBLOCK ; GOTO label "ELSEBLOCK" if S flag is set call .foo ; this is the "if" black, call foo() j FINISH ; GOTO FINISH; skip over the "else" block ELSEBLOCK: ; label this location to the assembler call .bar FINISH: ; both paths end up here ret ; return
Observe cómo el "bool" nunca se almacena en ningún lugar.
fuente
Prácticamente no se puede establecer el valor de encontrado. La depuración de programas optimizados rara vez vale la pena, el compilador puede reorganizar el código de manera que no corresponda de ninguna manera al código fuente (aparte de producir el mismo resultado), lo que confunde a los depuradores sin fin.
fuente
Al depurar programas optimizados (que puede ser necesario si el error no aparece en las compilaciones de depuración), a menudo debe comprender el compilador de ensamblado generado.
En su caso particular, el valor de retorno de
cpnd_find_exact_ckptinfo
se almacenará en el registro que se utiliza en su plataforma para los valores de retorno. Síix86
, eso sería%eax
. Activadox86_64
:,%rax
etc. Es posible que deba buscar en Google '[su procesador] procedimiento que llama a la convención' si no es ninguno de los anteriores.Puede examinar ese registro
GDB
y configurarlo. Por ejemplo, enix86
:(gdb) p $eax (gdb) set $eax = 0
fuente
Estoy usando QtCreator con gdb.
Añadiendo
Funciona bien para mi
fuente