Wyszukiwanie w witrynie

Debugger GNU lub GDB: potężne narzędzie do debugowania kodu źródłowego programów Linux


Debuger odgrywa kluczową rolę w każdym systemie tworzenia oprogramowania. Nikt nie jest w stanie napisać od razu kodu wolnego od błędów. W trakcie rozwoju zgłaszane są błędy, które należy rozwiązać w celu dalszego ulepszenia. System programistyczny jest niekompletny bez debugera. Biorąc pod uwagę społeczność programistów open source, GNU Debugger jest ich najlepszym wyborem. Jest również używany do tworzenia oprogramowania komercyjnego na platformach typu UNIX.

GNU Debugger, znany również jako gdb, pozwala nam przemycić kod podczas jego wykonywania lub dowiedzieć się, co program próbował zrobić w chwili przed awarią. GDB zasadniczo pomaga nam zrobić cztery główne rzeczy, aby wychwycić błędy w kodzie źródłowym.

  1. Uruchom program, podając argumenty, które mogą mieć wpływ na ogólne zachowanie.
  2. Zatrzymaj program w określonych warunkach.
  3. Sprawdź awarię lub moment zatrzymania programu.
  4. Zmień kod i natychmiast eksperymentuj ze zmodyfikowanym kodem.

Możemy używać gdb do debugowania programów napisanych w C i C++ bez większego wysiłku. Obecnie obsługa innych języków programowania, takich jak D, Modula-2, Fortran, jest częściowa.

Pierwsze kroki z debugerem GNU lub GDB

GDB wywołuje się za pomocą polecenia gdb. Po wydaniu gdb wyświetla pewne informacje o platformie i przenosi Cię do monitu (gdb), jak pokazano poniżej .

[root@fedora20 ~]# gdb
Przykładowe wyjście
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)

Wpisz help list, aby wyświetlić różne klasy poleceń dostępnych w gdb. Wpisz help , a po nim nazwę klasy, aby wyświetlić listę poleceń w tej klasie. Wpisz pomoc wszystkim, aby wyświetlić listę wszystkich poleceń. Skróty nazw poleceń są dozwolone, jeżeli są jednoznaczne. Możesz na przykład wpisać n zamiast next lub c, aby kontynuować i tak dalej.

Najczęściej używane polecenia GDB

Często używane polecenia gdb wymieniono w poniższej tabeli. Poleceń tych należy używać z poziomu wiersza poleceń gdb (gdb).

Command

Opis

run

Rozpocznij wykonywanie programu

quit

Zamknij gdb

print expr

Wydrukuj wyrażenie, gdzie wyrażenie może być także nazwą zmiennej

next

Przejdź do następnej linii

step

Przejdź do następnej linii

continue

Kontynuuj od bieżącego wiersza do końca programu lub następnego punktu przerwania

Zwróć uwagę na różnicę między dwoma poleceniami krok i następny. Polecenie next nie wchodzi do wnętrza funkcji, jeśli następna linia jest wywołaniem funkcji. Natomiast polecenie krok może wejść do funkcji wewnętrznej i zobaczyć, co się tam stanie.

Przykładowa sesja z GDB

Rozważ następujący kod źródłowy.


// 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; 
}

Aby zdebugować plik wyjściowy, musimy go skompilować z opcją -g do gcc w następujący sposób.

gcc -g sum.c -o sum

Plik wyjściowy sum można dołączyć do gdb na jeden z następujących 2 sposobów:

1. Określając plik wyjściowy jako argument gdb.

gdb sum

2. Uruchomienie pliku wyjściowego w gdb za pomocą polecenia file.

gdb
(gdb) file sum

Polecenie list wyświetla listę wierszy w pliku kodu źródłowego i przesuwa wskaźnik. Zatem pierwsza lista wyświetli pierwsze 10 linii, następna lista wyświetli kolejne 10 i tak dalej.

(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;

Aby rozpocząć wykonanie, wydaj polecenie uruchom . Teraz program zostanie wykonany normalnie. Ale zapomnieliśmy umieścić kilka punktów przerwania w kodzie źródłowym na potrzeby debugowania, prawda? Te punkty przerwania można określić dla funkcji lub w określonych liniach.

(gdb) b main

Uwaga: użyłem skrótu b dla określenia przerwa.

Po ustawieniu punktu przerwania w funkcji głównej, ponowne uruchomienie programu zatrzyma się na linii 11. To samo można zastosować, jeśli numer linii jest wcześniej znany.

(gdb) b sum.c:11

Teraz przejdź przez kolejne wiersze kodu, używając polecenia next lub n. Należy pamiętać, że polecenie next nie wchodzi do kodu funkcji, chyba że w funkcji ustawiony jest punkt przerwania. Wypróbujmy teraz polecenie drukuj. Ustaw punkt przerwania sumy funkcji jak poniżej.

(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]

Jeśli uruchamiany program wymaga parametrów wiersza poleceń, podaj je wraz z poleceniem uruchom jako.

(gdb) run   . . .

Pliki bibliotek współdzielonych powiązane z aktualnie uruchomionym programem mogą być wyświetlane jako.

(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

Modyfikowanie zmiennych

GDB może także modyfikować zmienne w trakcie wykonywania programu. Wypróbujmy to. Jak wspomniano powyżej, ustaw punkt przerwania w linii 16 i uruchom 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

Teraz a=1, b=2, a wynik powinien wynosić z=3. Ale tutaj zmieniliśmy końcowy wynik na z=4 w funkcji głównej. W ten sposób debugowanie może być łatwiejsze przy użyciu gdb.

Włącz/wyłącz punkty przerwania

Aby wyświetlić listę wszystkich punktów przerwania, wpisz informacje o punktach przerwania.

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

Tutaj jest tylko jeden punkt przerwania i jest nim Do. włączone wyłącz punkty przerwania określ numer punktu przerwania za pomocą polecenia wyłącz. Aby później włączyć, użyj polecenia włącz.

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

Możesz także usunąć punkty przerwania za pomocą polecenia delete.

Debugowanie uruchomionych procesów

W systemie GNU/Linux w tle działa wiele procesów. Aby zdebugować działający proces, przede wszystkim musimy znaleźć identyfikator procesu tego konkretnego procesu. Polecenie pidof podaje pid procesu.

pidof <process_name>

Teraz musimy dołączyć ten pid do gdb. Istnieją 2 sposoby.

1. Określając pid wraz z gdb.

gdb -p <pid>

2. Używając polecenia attach z gdb.

(gdb) attach <pid>

To wszystko na teraz. To tylko podstawy gdb, które pomogą Ci dobrze rozpocząć debugowanie kodu źródłowego, a to znacznie więcej niż to, co wyjaśniono powyżej. Na przykład możemy debugować, korzystając z informacji o stosie, zmiennych środowiskowych i wielu innych. Spróbuj pobawić się tymi wszystkimi rzeczami…