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
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).
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;
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?
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.
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.
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
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
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