GDB - Szybki przewodnik

Debugger to program, który uruchamia inne programy, umożliwiając użytkownikowi sprawowanie kontroli nad tymi programami i badanie zmiennych w przypadku wystąpienia problemów.

Debugger GNU, który jest również nazywany gdb, to najpopularniejszy debugger dla systemów UNIX do debugowania programów C i C ++.

GNU Debugger pomaga w uzyskaniu informacji na następujące tematy:

  • Jeśli zdarzył się zrzut pamięci, to na jakiej instrukcji lub wyrażeniu wystąpił błąd programu?

  • Jeśli podczas wykonywania funkcji wystąpi błąd, który wiersz programu zawiera wywołanie tej funkcji i jakie są parametry?

  • Jakie są wartości zmiennych programu w określonym momencie podczas wykonywania programu?

  • Jaki jest wynik określonego wyrażenia w programie?

Jak debuguje GDB?

GDB umożliwia uruchomienie programu do określonego punktu, a następnie zatrzymanie i wydrukowanie wartości pewnych zmiennych w tym punkcie lub przejście przez program po jednym wierszu na raz i wydrukowanie wartości każdej zmiennej po wykonaniu każdego wiersza.

GDB używa prostego interfejsu wiersza poleceń.

Zwraca uwagę

  • Mimo że GDB może pomóc w wykrywaniu błędów związanych z wyciekiem pamięci, nie jest narzędziem do wykrywania wycieków pamięci.

  • GDB nie może być używane dla programów, które kompilują się z błędami i nie pomaga w naprawianiu tych błędów.

Przed przystąpieniem do instalacji sprawdź, czy masz już zainstalowany gdb w systemie Unix, wydając następujące polecenie:

$gdb -help

Jeśli GDB jest zainstalowany, wyświetli wszystkie dostępne opcje w GDB. Jeśli GDB nie jest zainstalowany, przejdź do nowej instalacji.

Możesz zainstalować GDB w swoim systemie, wykonując proste kroki omówione poniżej.

step 1: Upewnij się, że masz wymagania wstępne do zainstalowania gdb:

  • Kompilator C zgodny z ANSI (zalecany jest gcc - pamiętaj, że gdb może debugować kody generowane przez inne kompilatory)

  • Wymagane jest 115 MB wolnego miejsca na partycji, na której chcesz zbudować gdb.

  • Wymagane jest 20 MB wolnego miejsca na partycji, na której zamierzasz zainstalować gdb.

  • Program dekompresyjny GNU, gzip

  • Plik make narzędzie - wiadomo, że wersja GNU działa bez problemu, inne prawdopodobnie też.

step 2: Pobierz dystrybucję źródłową gdb z ftp.gnu.org/gnu/gdb. (Użyliśmy gdb-6.6.tar.gz instrukcje.) Umieść pliki dystrybucyjne w katalogu kompilacji.

step 3:W katalogu kompilacji zdekompresuj gdb-6.6.tar.gz i wyodrębnij pliki źródłowe z archiwum. Po zakończeniu rozpakowywania plików zmień katalog roboczy na katalog gdb-6.6, który został automatycznie utworzony w katalogu kompilacji.

$ build> gzip -d gdb-6.6.tar.gz 
$ build> tar xfv gdb-6.6.tar 
$ build> cd gdb-6.6

step 4: Uruchom skrypt konfiguracyjny, aby skonfigurować drzewo źródłowe dla swojej platformy.

$ gdb-6.6> .⁄configure

step 5: Skompiluj gdb przy użyciu make użyteczność.

$ gdb-6.6> make

step 6: Zaloguj się jako root i zainstaluj gdb za pomocą następującego polecenia.

$ gdb-6.6> make install

step 7: W razie potrzeby miejsce na dysku można odzyskać, usuwając katalog budowania gdb i plik archiwum po zakończeniu instalacji.

$ gdb-6.6> cd .. 
$ build> rm -r gdb-6.6 
$ build> rm gdb-6.6.tar

Masz teraz zainstalowany gdb w swoim systemie i jest gotowy do użycia.

ZA Debugging Symbol Tableodwzorowuje instrukcje w skompilowanym programie binarnym na odpowiadające im zmienne, funkcje lub wiersze w kodzie źródłowym. To mapowanie może wyglądać następująco:

  • Instrukcja programu ⇒ nazwa pozycji, typ pozycji, oryginalny plik, zdefiniowany numer linii.

Tabele symboli mogą być osadzone w programie lub przechowywane jako osobny plik. Jeśli więc planujesz debugować swój program, konieczne jest utworzenie tabeli symboli, która będzie zawierała informacje wymagane do debugowania programu.

Możemy wnioskować o następujących faktach dotyczących tablic symboli:

  • Tablica symboli działa dla określonej wersji programu - jeśli program się zmieni, należy utworzyć nową tablicę.

  • Kompilacje debugowania są często większe i wolniejsze niż wersje detaliczne (bez debugowania); Kompilacje debugowania zawierają tablicę symboli i inne informacje pomocnicze.

  • Jeśli chcesz debugować program binarny, którego sam nie skompilowałeś, musisz uzyskać tablice symboli od autora.

Aby umożliwić GDB odczytanie wszystkich tych informacji wiersz po wierszu z tablicy symboli, musimy skompilować je nieco inaczej. Zwykle kompilujemy nasze programy jako:

gcc hello.cc -o hello

Zamiast robić to, musimy skompilować się z flagą -g, jak pokazano poniżej:

gcc -g hello.cc -o hello

GDB oferuje dużą listę poleceń, jednak najczęściej używane są następujące polecenia:

  • b main - Umieszcza punkt przerwania na początku programu

  • b - Wstawia punkt przerwania w bieżącej linii

  • b N - Wstawia punkt przerwania w linii N

  • b +N - Wstawia punkt przerwania N linii w dół od bieżącej linii

  • b fn - Wstawia punkt przerwania na początku funkcji „fn”

  • d N - usuwa punkt przerwania numer N

  • info break - lista punktów przerwania

  • r - Uruchamia program do punktu przerwania lub błędu

  • c - Kontynuuje działanie programu aż do następnego punktu przerwania lub błędu

  • f - Działa do zakończenia bieżącej funkcji

  • s - Uruchamia następną linię programu

  • s N - Uruchamia następne N wierszy programu

  • n - Podobnie jak s, ale nie wchodzi w funkcje

  • u N - Działa do momentu uzyskania N linii przed bieżącą linią

  • p var - Drukuje bieżącą wartość zmiennej „var”

  • bt - Drukuje ślad stosu

  • u - Podnosi poziom w stosie

  • d - Spada poziom w stosie

  • q - Kończy gdb

Pierwsze kroki: uruchamianie i zatrzymywanie

  • gcc -g myprogram.c

    • Kompiluje myprogram.c z opcją debugowania (-g). Nadal otrzymujesz plik a.out, ale zawiera on informacje o debugowaniu, które pozwalają na używanie zmiennych i nazw funkcji wewnątrz GDB zamiast surowych lokalizacji pamięci (nie jest to zabawne).

  • gdb a.out

    • Otwiera GDB z plikiem a.out, ale nie uruchamia programu. Zobaczysz znak zachęty (gdb) - wszystkie przykłady pochodzą z tego znaku zachęty.

  • r

  • r arg1 arg2

  • r <plik1

    • Trzy sposoby uruchomienia „a.out”, załadowane wcześniej. Możesz uruchomić go bezpośrednio (r), przekazać argumenty (r arg1 arg2) lub przesłać do pliku. Zazwyczaj przed uruchomieniem ustawiasz punkty przerwania.

  • help

  • h punktów przerwania

    • Wyświetla listę tematów pomocy (pomoc) lub uzyskuje pomoc na określony temat (punkty przerwania h). GDB jest dobrze udokumentowany.

  • q - Zamknij GDB

Przechodzenie przez kod

Stepping pozwala prześledzić ścieżkę programu i skupić się na kodzie, który ulega awarii lub zwraca nieprawidłowe dane wejściowe.

  • l

  • l 50

  • Moja funkcja

    • Wyświetla 10 wierszy kodu źródłowego dla bieżącego wiersza (l), określonego wiersza (l 50) lub funkcji (l moja funkcja).

  • Kolejny

    • Uruchamia program do następnej linii, a następnie zatrzymuje się. Jeśli bieżąca linia jest funkcją, wykonuje całą funkcję, a następnie zatrzymuje się.next jest dobry do szybkiego przechodzenia przez kod.

  • krok

    • Uruchamia następną instrukcję, a nie wiersz. Jeśli bieżąca instrukcja ustawia zmienną, jest taka sama jaknext. Jeśli jest to funkcja, wskoczy do niej, wykona pierwszą instrukcję, a następnie zatrzyma się.step jest dobry do zagłębiania się w szczegóły kodu.

  • koniec

    • Kończy wykonywanie bieżącej funkcji, a następnie wstrzymuje (nazywane również wyjściem). Przydatne, jeśli przypadkowo wszedłeś do funkcji.

Punkty przerwania lub punkty obserwacyjne

Punkty przerwania odgrywają ważną rolę w debugowaniu. Wstrzymują (przerywają) program, gdy osiąga określony punkt. Możesz sprawdzać i zmieniać zmienne oraz wznowić wykonywanie. Jest to pomocne, gdy wystąpi awaria wejścia lub wejścia mają być testowane.

  • przerwa 45

  • złamać moją funkcję

    • Ustawia punkt przerwania w linii 45 lub w mojej funkcji. Program zatrzyma się, gdy osiągnie punkt przerwania.
  • zegarek x == 3

    • Ustawia punkt obserwacyjny, który wstrzymuje program, gdy zmienia się warunek (gdy zmienia się x == 3). Punkty obserwacyjne są świetne dla niektórych danych wejściowych (myPtr! = NULL) bez konieczności przerywania każdego wywołania funkcji.

  • kontyntynuj

    • Wznawia wykonywanie po wstrzymaniu przez punkt przerwania / obserwacyjny. Program będzie kontynuowany, dopóki nie osiągnie następnego punktu przerwania / obserwacyjnego.

  • usuń N

    • Usuwa punkt przerwania N (punkty przerwania są numerowane podczas tworzenia).

Ustawianie zmiennych

Przeglądanie i zmienianie zmiennych w czasie wykonywania jest krytyczną częścią debugowania. Spróbuj podać nieprawidłowe dane wejściowe do funkcji lub uruchomić inne przypadki testowe, aby znaleźć główną przyczynę problemów. Zazwyczaj będziesz przeglądać / ustawiać zmienne, gdy program zostanie wstrzymany.

  • drukuj x

    • Wyświetla aktualną wartość zmiennej x. Możliwość używania oryginalnych nazw zmiennych jest powodem, dla którego potrzebna jest flaga (-g); programy kompilowane regularnie usuwają te informacje.

  • zestaw x = 3

  • ustaw x = y

    • Ustawia x na ustawioną wartość (3) lub na inną zmienną (y)
  • zadzwoń do myfunction ()

  • zadzwoń do mojej innej funkcji (x)

  • zadzwoń do strlen (mystring)

    • Wywołuje funkcje zdefiniowane przez użytkownika lub funkcje systemowe. Jest to niezwykle przydatne, ale uważaj na wywoływanie błędnych funkcji.

  • wyświetlacz x

    • Stale wyświetla wartość zmiennej x, która jest pokazywana po każdym kroku lub pauzie. Przydatne, jeśli stale sprawdzasz określoną wartość.

  • undisplay x

    • Usuwa stałe wyświetlanie zmiennej wyświetlanej przez polecenie wyświetlania.

Śledzenie wstecz i zmienianie ramek

Stos to lista bieżących wywołań funkcji - pokazuje, gdzie jesteś w programie. Rama przechowuje dane pojedynczego wywołania funkcji, takich jak argumenty.

  • bt

    • Backtraceslub wyświetla bieżący stos funkcji, aby pokazać, gdzie jesteś w bieżącym programie. Jeśli main wywołuje funkcję a (), która wywołuje b (), która wywołuje c (), śledzenie wstecz jest

  • c <= current location 
    b 
    a 
    main
  • up

  • na dół

    • Przejdź do następnej klatki w górę lub w dół na stosie funkcji. Jeśli jesteś wc, możesz się przenieść b lub a do badania zmiennych lokalnych.

  • powrót

    • Zwraca z bieżącej funkcji.

Obsługa sygnałów

Sygnały to komunikaty generowane po pewnych zdarzeniach, takich jak licznik czasu lub błąd. GDB może wstrzymać się, gdy napotka sygnał; zamiast tego możesz je zignorować.

  • uchwyt [nazwa sygnału] [akcja]

  • uchwyt SIGUSR1 nostop

  • uchwyt SIGUSR1 noprint

  • uchwyt SIGUSR1 ignoruj

    • Poinstruuj GDB, aby ignorował określony sygnał (SIGUSR1), gdy wystąpi. Istnieją różne poziomy ignorowania.

Zapoznaj się z poniższymi przykładami, aby zrozumieć procedurę debugowania programu i zrzucania jądra.

  • Przykład debugowania 1

    Ten przykład pokazuje, jak można uchwycić błąd, który występuje z powodu wyjątku zgłoszonego podczas dzielenia przez zero.

  • Przykład debugowania 2

    Ten przykład ilustruje program, który może zrzucić rdzeń z powodu niezainicjowanej pamięci.

Oba programy są napisane w C ++ i generują zrzut pamięci z różnych powodów. Po przejrzeniu tych dwóch przykładów powinieneś być w stanie debugować programy w C lub C ++ generujące zrzuty jądra.

Po przejściu przez ten samouczek, musisz dobrze zrozumieć debugowanie programu C lub C ++ za pomocą GNU Debugger. Teraz nauczenie się funkcjonalności innych debuggerów powinno być bardzo łatwe, ponieważ są one bardzo podobne do GDB. Zdecydowanie zalecamy zapoznanie się z innymi debugerami, aby zapoznać się z ich funkcjami.

Na rynku dostępnych jest kilka dobrych debuggerów:

  • DBX Debugger- Ten debugger jest dostarczany wraz z Sun Solaris i możesz uzyskać pełne informacje o tym debugerze, korzystając ze strony podręcznika dbx, tj. Man dbx .

  • DDD Debugger- To jest graficzna wersja dbx, dostępna bezpłatnie w systemie Linux. Aby uzyskać szczegółowe informacje, użyj strony podręcznika man ddd, tj. Man ddd .

Szczegółowe informacje na temat Debuggera GNU można uzyskać pod następującym linkiem: Debugowanie za pomocą GDB