This is an old revision of the document!
GDB, sau (G)NU (D)e(B)ugger, este un utilitar ce poate fi folosit pentru a vedea ce se întâmplă înăuntrul unui program în timp ce acesta rulează sau pentru a putea vedea starea în care se află programul la momentul în care a crash-uit.
GDB este folosit în principal pentru a depana programe scrise în C sau C++. Acesta poate fi folosit în două moduri pentru a depana un program:
- rulându-l folosind comanda gdb - folosind fişierul core generat în urma unei erori grave (de obicei segmentation fault)
În acest laborator vom analiza doar prima modalitate de depanare.
Pentru exemplificare considerăm următorul program:
int add(int a, int b) { int c; c = a + b; return c; } int main(int argc, char **argv) { char *bug = 0; bug[2] = add(2, 4); return 0; }
După compilare, observăm că la executarea programului se produce un segmentation fault.
$ gcc bug.c -o bug $ ./bug Segmentation fault (core dumped)
gdb
este unealta potrivită pentru astfel de situații. Ca să aflăm la ce linie a avut loc acest segmentation fault, mai întâi trebuie să revenim la pasul de compilare și să activăm simbolurile de depanare folsind opțiunea -g
a compilatorului gcc
:
$ gcc -g bug.c -o bug
În continuare, rulăm programul folosind gdb
:
$ gdb bug [...] (gdb) run Program received signal SIGSEGV, Segmentation fault. 0x000000000040054f in main (argc=1, argv=0x7fffffffe038) at bug.c:13 13 bug[2] = add(2, 4); (gdb)
Simbolurile de depanare nu sunt în mod implicit adăugate deoarece prin adăugarea acestora, executabilul rezultat va avea o dimensiune mai mare. Folosiți opțiunea -g
doar în faza de dezvoltare.
$ gcc exemplu.c -o exemplu $ gcc -g exemplu.c -o exemplu_debug $ ls -l -rwxrwxr-x. 1 student student 6.0K Dec 7 23:55 exemplu -rwxrwxr-x. 1 student student 6.8K Dec 7 23:55 exemplu_debug
Câteva din comenzile de bază în gdb
sunt:
[...] (gdb) break main # adăugăm breakpoint în funcția main Breakpoint 1 at 0x400530: file bug.c, line 12. (gdb) run # pornim programul Starting program: /home/master/github/labs/ii/bug Breakpoint 1, main (argc=1, argv=0x7fffffffe038) at bug.c:12 12 char *bug = 0; (gdb) next # trecem la următoarea linie din codul sursă 13 bug[2] = add(2, 4); (gdb) next Program received signal SIGSEGV, Segmentation fault. 0x000000000040054f in main (argc=1, argv=0x7fffffffe038) at bug.c:13 13 bug[2] = add(2, 4); (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/master/github/labs/ii/bug Breakpoint 1, main (argc=1, argv=0x7fffffffe038) at bug.c:12 12 char *bug = 0; (gdb) next 13 bug[2] = add(2, 4); (gdb) step # intrăm în funcția add pentru a o analiza pas cu pas add (a=2, b=4) at bug.c:6 6 c = a + b; (gdb) next 7 return c; (gdb) next 8 } (gdb) next Program received signal SIGSEGV, Segmentation fault. 0x000000000040054f in main (argc=1, argv=0x7fffffffe038) at bug.c:13 13 bug[2] = add(2, 4); (gdb) quit A debugging session is active. Inferior 1 [process 331] will be killed. Quit anyway? (y or n) y
* print - cu ajutorul acesteia se pot afişa valorile variabilelor din funcţia curentă sau a variabilelor globale. print poate primi ca argument şi expresii complicate (dereferenţieri de pointeri, referenţieri ale variabilelor, expresii aritmetice, aproape orice expresie C validă). În plus, print poate afişa structuri de date precum struct şi union sau evalua funcţii şi întoarcerea rezultatului lor. * list - afișează o parte din fișierul sursă al programulu debanat. * backtrace - afișează un backtrace. Un backtrace afișează, în ordine inversă, funcțiile ce au fost apelate pentru a se ajunge la linia curentă. *