Narzędzia debugowania kodu Narzędzia debugowania kodu 1/33
Narzędzia debugowania kodu 2/33 Oprogramowanie zawiera błędy Oprogramowanie zawsze zawiera błędy Odpluskwianie programów jest zajęciem programistów
Narzędzia debugowania kodu 3/33 Możliwości znajdowania błędów Na szanse znalezienia błędów mają wpływ: odpowiedni kod źródłowy narzędzia makrodefinicje flagi kompilatora narzędzia statycznej analizy odpowiednie biblioteki opcje linkera przypadki testowe debugery
Narzędzia debugowania kodu 4/33 Dobre praktyki znajdowania błędów Złote zasady zrozumienie wymagań spowodowanie błędu najprostszy przypadek testowy właściwy komunikat błędu najprostsze rozwiązania (sprawdź wtyczkę) oddzielenie faktów od interpretacji dziel i zwyciężaj
Narzędzia debugowania kodu 5/33 Dobre praktyki znajdowania błędów Złote zasady cd. odpowiednie narzędzie do danego błędu jedna zmiana na raz zachowanie przebiegu zmian świeże spojrzenie jeśli coś nie zostało poprawione, to błąd nie jest naprawiony pokrycie poprawki testem regresyjnym
Narzędzia debugowania kodu 6/33 Prawidłowy warsztat pracy miej zainstalowane i przetestowane (oprócz kompilatora): debuger kodu źródłowego debuger pamięci narzędzie do profilowania kodu bądź pewny kompatybilności debugera i kompilatora utrzymuj i wykonuj testy jednostkowe zautomatyzuj powtarzane czynności
Narzędzia debugowania kodu 7/33 Rodzaje błędów błąd powszechny błąd sporadyczny błąd tajemniczy (Heisenbug) wyścigowiec naruszenie pamięci idealista
Narzędzia debugowania kodu 8/33 Wizualizacja zachowania programu $ gdb./hello GNU gdb (GDB) 7.0-ubuntu Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+:... Reading symbols from /home/../przyklady/hello...done. (gdb) start Temporary breakpoint 1 at 0x804863d: file hello.cpp, line 4. Starting program: /home/../przyklady/hello Temporary breakpoint 1, main (argc=1, argv=0xbffff9b4) at hello. 4 std::cout << "Hello world!\n"; (gdb) list 1 #include <iostream> 2 3 int main(int argc, char *argv[]) { 4 std::cout << "Hello world!\n"; 5 return 0; 6 } (gdb)
Narzędzia debugowania kodu 9/33 Uruchamianie programu Opcje kompilacji $ g++ -g... Debuger gdb $ gdb./program Uruchomienie programu run start Ctrl-C pauza continue
Narzędzia debugowania kodu 10/33 Punkty wstrzymania programu (breakpoints) Rodzaje: w określonej linii na funkcji warunkowe zdarzenia
Narzędzia debugowania kodu 11/33 Sterowanie przebiegiem programu Krokowe wykonywanie programu step-into (step) step-over (next) step-out (finish)
Narzędzia debugowania kodu 12/33 Zmienne i wyrażenia print wypisanie danych zgodnie z podanym formatowaniem examine wypisanie surowych danych display wyświetla wyrażenie za każdym razem, gdy program wstrzymuje pracę
Narzędzia debugowania kodu 13/33 Zrzuty rdzenia (ang. core dumps) Aby umożliwić systemowi wykonywanie zrzutów: $ ulimit -c unlimited Wczytanie zrzutu do debugera $ gdb./program core Core was generated by./a.out. Program terminated with signal 8, Arithmetic exception. [New process 7713] #0 0x0000000000400586 in foo () at crash.cpp:3 3 return 1/0; (gdb) bt #0 0x0000000000400586 in foo () at crash.cpp:3 #1 0x000000000040059e in main (argc=1, argv=0x7fffffffcd88) at crash.cpp:7
Narzędzia debugowania kodu 14/33 Podstawy pracy (gdb) sh Ambiguous command "sh": sharedlibrary, shell, show. (gdb) b<tab><tab> backtrace break bt (gdb) b
Narzędzia debugowania kodu 15/33 Pomoc dostępna wewnątrz debugera (gdb) help List of classes of commands: aliases -- Aliases of other commands breakpoints -- Making program stop at certain points... stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the user-defined -- User-defined commands Type "help" followed by a class name for a list of commands in t Type "help all" for the list of all commands. Type "help" followed by command name for full documentation. Type "apropos word" to search for commands related to "word". Command name abbreviations are allowed if unambiguous.
Narzędzia debugowania kodu 16/33 Składnia poleceń tworzących punkty wstrzymania (1) Przykłady (gdb) b # Wstrzymuje wykonywanie na kolejnym rozkazie bieżącej ramki stosu (gdb) b foo # Wstrzymuje wykonanie na wywołaniu funkcji foo (gdb) b foobar.c:foo # Wstrzymuje wykonywanie na wywołaniu funkcji foo, zdefiniowanej w pliku foobar.c
Narzędzia debugowania kodu 17/33 Składnia poleceń tworzących punkty wstrzymania (2) Przykłady (gdb) b 10 # Wstrzymuje wykonywanie na dziesiątym wierszu bieżącego modułu (gdb) b foobar.c:10 # Wstrzymuje wykonanie na dziesiątym wierszu pliku foobar.c (gdb) b *0xdeadbeef # Wstrzymuje wykonywanie na na adresie 0xdeadbeef
Narzędzia debugowania kodu 18/33 Stosowanie oczekujących punktów wstrzymania $ gdb./a.out... (gdb) b memset Function "memset" not defined. Make breakpoint pending on future shared library load? (y o Breakpoint 1 (memset) pending. (gdb) run 100 Starting program... Breakpoint 2 at 0xb7e4e050 Pending breakpoint "memset" resolved Breakpoint 2, 0xb7e4e050 in memset () from /lin/tls/libc.so (gdb)
Narzędzia debugowania kodu 19/33 Stosowanie warunkowych punktów wstrzymania (gdb) b nasty if setlen > buflen Breakpoint 1 at 0x804843e: file nasty.c, line 8. (gdb) run 100 Starting program... Breakpoint 1, nasty (buf=0x804a008 "", setlen=100) at nasty 8 return memset(buf, a, setlen); (gdb) b nasty if main::len > buflen Breakpoint 1 at 0x804845e: file nasty.c, line 8
Narzędzia debugowania kodu 20/33 Stosowanie punktów obserwacyjnych (1) Składnia (gdb) watch foo (gdb) watch *foo (gdb) watch foo if someval == 1 (gdb) watch buf[len]
Narzędzia debugowania kodu 21/33 Stosowanie punktów obserwacyjnych (2) Rodzaje punktów obserwacyjnych watch wstrzymuje wykonywanie programu w momencie zapisu wartości w miejscu nadzorowanym przez wyrażenie rwatch wstrzymuje wykonywanie programu w momencie odczytu wartości z miejsca nadzorowanego przez wyrażenie awatch wstrzymuje wykonywanie programu w momencie odczytu lub zapisu wartości w miejscu nadzorowanym przez wyrażenie
Narzędzia debugowania kodu 22/33 Analiza i modyfikowanie danych whatis wyświetla informacje o typie danego symbolu backtrace prezentuje stos wywołań bieżącego programu up, down zmienia ramkę stosu frame umożliwia wskazanie konkretnej ramki stosu info locals wyświetla listę wszystkich zmiennych lokalnych
Narzędzia debugowania kodu 23/33 Składnia wyrażenia print Sesja wykorzystująca print: (gdb) whatis foo type = long long int (gdb) p foo $2 = 4096 (gdb) x foo 0x1000: Cannot access memory at address 0x1000 (gdb) x &foo 0xbf9af240: 0x00001000 (gdb) p/x foo $2 = 0x1000 (gdb) x/d &foo 0x22eec4: 4096
Narzędzia debugowania kodu 24/33 Modyfikatory danych wyjściowych polecenia print Modyfikator x d u o b a c d Format szesnastkowy dziesiętny ze znakiem dziesiętny bez znaku ósemkowy binarny adres (wyświetla adres w systemie szesnastkowym i prezentuje relacje łączące ten adres z pobliskimi symbolami) znakowy (najmniej znaczący bajt) zmiennoprzecinkowy (wyświetla wartość pamięci w formie wartości typu double
Modyfikatory danych wyjściowych polecenia examine Modyfikator x d u o b a c d i s Format szesnastkowy dziesiętny ze znakiem dziesiętny bez znaku ósemkowy binarny adres (wyświetla dane szesnastkowe wraz z odniesieniami do pobliskich symboli) znakowy (zrzuca pamięć w parach obejmujących znaki ASCII oraz bajty w formie wartości dziesiętnych) zmiennoprzecinkowy (wyświetla wartość pamięci w formie wartości typu float rozkazy (dezasembluje pamięć pod wskazanym adresem) łańcuch ASCII zakończony pustym znakiem Narzędzia debugowania kodu 25/33
Narzędzia debugowania kodu 26/33 Przykłady wyświetlania danych (1) Dane: int tab[] = {10, 20, 30, 40}; gdb: (gdb) p tab $1 = {10, 20, 30, 40} (gdb) x/4wx tab 0x8049610 <tab>: 0x0000000a 0x00000014 (gdb) x/2gx tab 0x8049610 <tab>: 0x0000001e 0x000000140000000a 0x000000280000001e 0x00000028
Narzędzia debugowania kodu 27/33 Przykłady wyświetlania danych (2) gdb: (gdb) p *tab $1 = 10 (gdb) p tab[1] $2 = 20 (gdb) p tab[1]@2 $3 = {20, 30}
Narzędzia debugowania kodu 28/33 Wywoływanie funkcji z poziomu debugera Wywoływanie funkcji bez podejmowania dodatkowych działań: (gdb) call getpid() $1 = 27274 (gdb) call kill($1,0) $2 = 0
Narzędzia debugowania kodu 29/33 Punkty wstrzymania w funkcjach C++ Pełna sygnatura (gdb) break C::foo(int) Interaktywne określanie (gdb) break C::foo [0] cancel [1] all [2] C::foo(std::string) at class.cpp:6 [3] C::foo(double) at class.cpp:5 [4] C::foo(int) at class.cpp:4 >
Narzędzia debugowania kodu 30/33 Punkty wstrzymania i szablony (gdb) rbreak swapval Breakpoint 1 at 0x80487e7: file swap.cpp, line 5. void void swapval<int>(int&, int&); Breakpoint 2 at 0x804880b: file swap.cpp, line 5. void void swapval<std::string>(std::string&, std::string&); (gdb) break void swapval< void swapval<int>(int&, int&) void swapval<std::string>(std::string&, std::string&) (gdb) break void swapval<
Narzędzia debugowania kodu 31/33 Kontenery biblioteki standardowej C++ Kod: std::vector<int> wek(3); std::list<int> lista; std::list<int>::iterator x = lista.begin() gdb: (gdb) whatis wek type = std::vector<int,std::allocator<int> > (gdb) p wek.size() $1 = 3 (gdb) p *x $2 = (int &) @0x804c1f8: 100
Narzędzia debugowania kodu 32/33 Punkty wstrzymywania i wyjątki C++ (gdb) catch throw Catchpoint 1 (throw) (gdb) run Starting program: /home/../a.out Catchpoint 1 (exception thrown), 0x001e8525 in cxa_throw from /usr/lib/libstdc++.so.6 (gdb)
Narzędzia debugowania kodu 33/33 W wykładzie wykorzystano materiały Thorsten Grötker, Ulrich Holtmann, Holger Keding, Markus Wloka, The Developer s Guide to Debugging, Springer, 2008 John Fusco, Linux. Niezbędnik programisty, Helion, 2009