c optimization compiler-construction gdb compilation

¿Por qué GDB salta impredeciblemente entre líneas e imprime variables como "<value optimised out"?



optimization compiler-construction (8)

Al depurar programas optimizados (que pueden ser necesarios si el error no aparece en las compilaciones de depuración), a menudo debe comprender el compilador ensamblado generado.

En su caso particular, el valor de retorno de cpnd_find_exact_ckptinfo se almacenará en el registro que se usa en su plataforma para los valores devueltos. En ix86 , eso sería %eax . En x86_64 : %rax , etc. Es posible que necesite buscar en google ''procedimiento de llamada [de su procesador] convención'' si no es ninguno de los anteriores.

Puede examinar ese registro en GDB y puede configurarlo. Por ejemplo, en ix86 :

(gdb) p $eax (gdb) set $eax = 0

¿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 se ejecuta de nuevo el mismo para 905 908 910?

Otra cosa que se found es una variable bool type, ¿por qué muestra el 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 ?


Casi no puedes establecer el valor de found. La depuración de programas optimizados rara vez vale la pena, el compilador puede reordenar el código de forma que no se corresponderá de ninguna manera con el código fuente (que no sea producir el mismo resultado), lo que confunde a los depuradores sin fin.


Declarar encontrado como "volátil". Esto debería decirle al compilador que NO lo optimice.

volatile int found = 0;


El compilador comenzará a hacer cosas muy inteligentes con las optimizaciones activadas. El depurador mostrará el código saltando hacia adelante y hacia atrás mucho debido a la forma optimizada en que las variables se almacenan 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 hábilmente entre los registros de velocidad, en lugar de tener una ubicación de memoria directa a la que el depurador puede acceder.

Compilar sin optimizaciones?


Estoy usando QtCreator con gdb.

Añadiendo

QMAKE_CXXFLAGS += -O0 QMAKE_CXXFLAGS -= -O1 QMAKE_CXXFLAGS -= -O2 QMAKE_CXXFLAGS -= -O3

Me funciona bien


Normalmente, los valores booleanos que se usan en las ramas inmediatamente después de que se calculan así nunca se almacenan realmente en las variables. En cambio, el compilador se ramifica directamente de los códigos de condición que se establecieron a partir de 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 compila a 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.


Para depurar el código optimizado, aprenda el lenguaje ensamblador / máquina.

Use el modo GDB TUI. Mi copia de GDB lo habilita cuando escribo el signo menos y Enter. Luego escriba Cx 2 (que es mantener presionado Control y presione X, suelte ambos y luego presione 2). Eso lo pondrá en la pantalla de fuente y desensamblaje divididos. Luego use stepi y nexti para mover una instrucción de máquina a la vez. Use Cx o para alternar entre las ventanas de TUI.

Descargue un PDF sobre el idioma de la máquina de su CPU y las convenciones de llamada a funciones. Aprenderá rápidamente a reconocer lo que se está haciendo con los argumentos de funciones y los valores de retorno.

Puede visualizar el valor de un registro usando un comando GDB como p $eax


Vuelva a compilar sin optimizaciones (-O0 en gcc).