Dlaczego GDB przeskakuje nieprzewidywalnie między wierszami i wypisuje zmienne jako""?

Czy ktoś może wyjaśnić to zachowanie 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.

Dlaczego po wykonaniu linii 903 ponownie wykonuje to samo dla 905 908 910?

Inna sprawa, że found jest zmienną typu bool, więc dlaczego pokazuje value optimized out? Nie jestem w stanie ustawić wartości found.

To wydaje się być optymalizacja kompilatora (w tym przypadku jego -O2); Jak mogę jeszcze ustawić wartość found?

8 answers

Aby debugować zoptymalizowany kod, naucz się języka assembly/machine.

Użyj trybu GDB TUI. Moja kopia GDB włącza ją, gdy wpisuję minus i wprowadzam. Następnie wpisz C - x 2 (czyli przytrzymaj Control i naciśnij X, zwolnij oba, a następnie naciśnij 2). To umieści go w podzielonym źródle i disassembly display. Następnie użyj stepi i nexti, aby przenieść jedną instrukcję maszynową na raz. Użyj C-x o, aby przełączać się między oknami TUI.

Pobierz plik PDF o języku maszynowym procesora i funkcji zwoływanie zjazdów. Szybko nauczysz się rozpoznawać, co robi się z argumentami funkcji i zwracanymi wartościami.

Możesz wyświetlić wartość rejestru używając komendy GDB, takiej jak p $eax

 113
Author: Zan Lynx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-30 19:56:50

Przekompiluj bez optymalizacji (- O0 na gcc).

 71
Author: D'Nabre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-30 20:04:13

Declare found as "volatile". To powinno powiedzieć kompilatorowi, aby go nie optymalizował.

volatile int found = 0;
 38
Author: BenB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-28 07:57:03

Kompilator zacznie robić bardzo sprytne rzeczy z włączoną optymalizacją. Debugger pokaże kod przeskakujący do przodu i do tyłu ze względu na zoptymalizowany sposób przechowywania zmiennych w rejestrach. Prawdopodobnie jest to powód, dla którego nie można ustawić zmiennej (lub w niektórych przypadkach zobaczyć jej wartość), ponieważ została ona sprytnie rozdzielona między rejestry pod kątem szybkości, zamiast mieć bezpośrednią lokalizację pamięci, do której debugger może uzyskać dostęp.

Kompilować bez optymalizacji?

 11
Author: kjfletch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-28 07:02:43

Zazwyczaj wartości logiczne, które są używane w gałęziach natychmiast po ich obliczeniu w ten sposób, nigdy nie są faktycznie przechowywane w zmiennych. Zamiast tego kompilator po prostu odgałęzia się bezpośrednio od kodów warunkowych , które zostały ustawione z poprzedniego porównania. Na przykład,

int a = SomeFunction();
bool result = --a >= 0; // use subtraction as example computation
if ( result ) 
{
   foo(); 
}
else
{
   bar();
}
return;

Zazwyczaj kompiluje się do czegoś takiego jak:

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

Zauważ, że "bool" nigdy nie jest nigdzie przechowywany.

 5
Author: Crashworks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-28 08:26:19

W zasadzie nie można ustawić wartości found. Debugowanie zoptymalizowanych programów rzadko jest warte kłopotu, kompilator może zmienić układ kodu w taki sposób, aby w żaden sposób nie odpowiadał kodowi źródłowemu (inny niż generowanie tego samego wyniku), co powoduje, że debuggery nie mają końca.

 4
Author: nos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-28 07:48:22

Podczas debugowania zoptymalizowanych programów (co może być konieczne, jeśli błąd nie pojawia się w kompilacjach debugowania), często musisz zrozumieć wygenerowany kompilator assembly.

W twoim konkretnym przypadku wartość zwracana cpnd_find_exact_ckptinfo będzie przechowywana w rejestrze, który jest używany na twojej platformie do zwracania wartości. Na ix86, czyli %eax. On x86_64: %rax, itd. Może być konieczne wygooglowanie "procedury [procesora] wywołującej konwencję", jeśli nie jest to żadna z powyższych.

Możesz to zbadać Zarejestruj się w GDB i możesz go ustawić. Np. na ix86:

(gdb) p $eax
(gdb) set $eax = 0 
 4
Author: Employed Russian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-29 04:19:56

Używam QtCreator z gdb.

Dodawanie

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

Działa dobrze dla mnie

 0
Author: Haselnussstrauch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 13:16:25