GNU Debugger ili GDB: Snažan alat za otklanjanje grešaka izvornog koda za Linux programe


Debuger igra vitalnu ulogu u svakom sistemu razvoja softvera. Niko ne može odjednom napisati kod bez grešaka. Tokom razvoja, pojavljuju se greške i potrebno ih je riješiti radi daljeg poboljšanja. Razvojni sistem je nepotpun bez debugera. Uzimajući u obzir zajednicu programera otvorenog koda, GNU Debugger je njihov najbolji izbor. Takođe se koristi za komercijalni razvoj softvera na platformama tipa UNIX.

GNU Debugger, također poznat kao gdb, omogućava nam da se provučemo kroz kod dok se izvršava ili ono što je program pokušavao da uradi u trenutku prije nego što se srušio. GDB nam u osnovi pomaže da uradimo četiri glavne stvari kako bismo uhvatili nedostatke u izvornom kodu.

  1. Pokrenite program, navodeći argumente koji mogu utjecati na općenito ponašanje.
  2. Zaustavite program pod određenim uslovima.
  3. Ispitajte pad ili kada je program zaustavljen.
  4. Promijenite kod i odmah eksperimentirajte s modificiranim kodom.

Možemo koristiti gdb za otklanjanje grešaka u programima napisanim u C i C++ bez mnogo truda. Od sada podrška za druge programske jezike kao što su D, Modula-2, Fortran je djelomična.

Početak rada s GNU Debuggerom ili GDB

GDB se poziva pomoću naredbe gdb. Prilikom izdavanja gdb, prikazuje neke informacije o platformi i spušta vas u (gdb) prompt kao što je prikazano ispod .

[root@fedora20 ~]# gdb
Sample Output
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 
Copyright (C) 2013 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law.  Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "x86_64-redhat-linux-gnu". 
Type "show configuration" for configuration details. 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>. 
Find the GDB manual and other documentation resources online at: 
<http://www.gnu.org/software/gdb/documentation/>. 
For help, type "help". 
Type "apropos word" to search for commands related to "word". 
(gdb)

Upišite help list da biste izbacili različite klase komandi dostupnih unutar gdb-a. Otkucajte help a zatim ime klase za listu naredbi u toj klasi. Unesite help all za listu svih naredbi. Skraćenice naziva naredbi su dozvoljene ako su nedvosmislene. Na primjer, možete upisati n umjesto da kucate next ili c za nastavi i tako dalje.

Najčešće korištene GDB naredbe

Često korištene gdb komande navedene su u sljedećoj tabeli. Ove komande se koriste iz gdb komandne linije (gdb).

Command

Opis

run

Pokreni izvršavanje programa

quit

Napusti gdb

print expr

Ispiši izraz gdje expr može biti i naziv varijable

next

Idi na sljedeći red

step

Zakoračite u sljedeći red

continue

Nastavite od trenutnog reda do kraja programa ili sljedeće tačke prekida

Obratite pažnju na razliku između dvije naredbe step i next. Komanda next ne ide unutar funkcije ako je sljedeći red poziv funkcije. Dok naredba step može ući u unutarnju funkciju i vidjeti šta se tamo događa.

Primer sesije sa GDB

Razmotrite sljedeći izvorni kod.


// sum.c
#include <stdio.h> 

int sum (int a, int b) { 
	int c; 
	c = a + b; 
	return c; 
} 

int main() { 
	int x, y, z; 
	printf("\nEnter the first number: "); 
	scanf("%d", &x); 
	printf("Enter the second number: "); 
	scanf("%d", &y); 
	z = sum (x, y); 
	printf("The sum is %d\n\n", z); 
	return 0; 
}

Da bismo debagirali izlaznu datoteku, moramo istu kompajlirati sa -g opcijom u gcc kako slijedi.

gcc -g sum.c -o sum

Izlazni fajl sum se može priložiti na gdb na bilo koji od sljedeća 2 načina:

1. Određivanjem izlazne datoteke kao argumenta za gdb.

gdb sum

2. Pokretanje izlazne datoteke unutar gdb-a pomoću naredbe file.

gdb
(gdb) file sum

Komanda list navodi redove u datoteci izvornog koda i pomiče pokazivač. Dakle, prva lista će prikazati prvih 10 redova, a sljedeća lista će prikazati sljedećih 10 i tako dalje.

(gdb) list
1	#include <stdio.h>   
2	 
3	int sum (int a, int b) { 
4		int c; 
5		c = a + b; 
6		return c; 
7	} 
8	 
9	int main() { 
10		int x, y, z;

Da započnete izvršavanje, izdajte naredbu pokreni . Sada se program normalno izvršava. Ali zaboravili smo da stavimo neke tačke prekida u izvorni kod za otklanjanje grešaka, zar ne? Ove tačke prekida mogu biti specificirane za funkcije ili na određenim linijama.

(gdb) b main

Napomena: Koristio sam skraćenicu b za prekid.

Nakon postavljanja tačke prekida na glavnoj funkciji, ponovno pokretanje programa će se zaustaviti na liniji 11. Ista stvar se može primijeniti ako je broj reda poznat prije.

(gdb) b sum.c:11

Sada koračajte kroz redove koda koristeći naredbu next ili n. Važno je napomenuti da naredba next ne ulazi unutar koda funkcije osim ako se na funkciji ne postavi tačka prekida. Isprobajmo sada naredbu print. Postavite tačku prekida na zbiru funkcije kao dolje.

(gdb) b sum 
Breakpoint 1 at 0x4005aa: file sum.c, line 5. 
(gdb) r 
Starting program: /root/sum 

Enter the first number: 2 
Enter the second number: 3 

Breakpoint 1, sum (a=2, b=3) at sum.c:5 
5		c = a + b; 
(gdb) p a 
$1 = 2 
(gdb) p b 
$2 = 3
(gdb) c 
Continuing. 
The sum is 5 

[Inferior 1 (process 3444) exited normally]

Ako program koji se pokreće zahtijeva parametre komandne linije, onda navedite iste zajedno sa naredbom pokreni kao.

(gdb) run   . . .

Datoteke zajedničke biblioteke povezane sa trenutnim pokrenutim programom mogu biti navedene kao.

(gdb) info share 
From                To                  Syms Read   Shared Object Library 
0x00000035a6000b10  0x00000035a6019c70  Yes         /lib64/ld-linux-x86-64.so.2 
0x00000035a641f560  0x00000035a6560bb4  Yes         /lib64/libc.so.6

Modificiranje varijabli

GDB također može mijenjati varijable tokom izvršavanja programa. Hajde da probamo ovo. Kao što je gore spomenuto, postavite tačku prekida u liniji 16 i pokrenite program.

(gdb) r 
Starting program: /root/sum 

Enter the first number: 1 
Enter the second number: 2 

Breakpoint 1, main ( ) at sum.c:16 
16		printf("The sum is %d\n\n", z); 
(gdb) set z=4 
(gdb) c 
Continuing. 
The sum is 4

Sada a=1, b=2 i rezultat bi trebao biti z=3. Ali ovdje smo promijenili konačni rezultat uz=4 u glavnoj funkciji. Na ovaj način otklanjanje grešaka može biti olakšano korištenjem gdb-a.

Omogući/onemogući tačke prekida

Da biste dobili listu svih tačaka prekida, unesite informacione tačke prekida.

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep y   0x00000000004005c2 in main at sum.c:11

Ovdje postoji samo jedna tačka prekida i to je To. omogućeno onemogućavanje tačaka prekida specificira broj tačke prekida zajedno sa naredbom onemogući. Da biste kasnije omogućili, koristite naredbu enable.

(gdb) disable 1 
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep n   0x00000000004005c2 in main at sum.c:11

Prelomne tačke možete obrisati i komandom delete.

Otklanjanje grešaka u pokrenutim procesima

Brojni procesi se pokreću u pozadini u GNU/Linux sistemu. Za otklanjanje grešaka u pokrenutom procesu prije svega moramo pronaći ID procesa tog određenog procesa. Naredba pidof daje pid procesa.

pidof <process_name>

Sada trebamo priložiti ovaj pid na gdb. Postoje 2 načina.

1. Određivanjem pid-a zajedno sa gdb.

gdb -p <pid>

2. Korištenje naredbe attach iz gdb-a.

(gdb) attach <pid>

To je sve za sada. Ovo su samo osnove gdb-a za dobar početak u otklanjanju grešaka izvornog koda i to je mnogo više od gore objašnjenih stvari. Na primjer, možemo otkloniti greške koristeći informacije o steku, varijabli okruženja i još mnogo toga. Pokušajte se poigrati sa svim ovim stvarima…