Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Odrobaczanie (debugging) programu

Podobne prezentacje


Prezentacja na temat: "Odrobaczanie (debugging) programu"— Zapis prezentacji:

1 Odrobaczanie (debugging) programu
Zasada van Tassela: Żaden program nie działa od razu. Bądź szczególnie podejrzliwy, jeżeli za pierwszym razem dostałeś poprawną odpowiedź. Pojęcie “robaka” (bug) w elektronicznej technice obliczeniowej przypisuje się admirał U.S. Navy, Grace Murray Hopper, twórczyni COBOLu, która opowiadała historię o techniku, który naprawił komputer Harvard II usuwając ćmę z obwodów. Cała historia jest opisana w Annals of the History of Computing, (1981). Później uogólniono to pojęcie na złe funkcjonowanie programów. Jeszcze wcześniej mianem “bug” określano defekty urządzeń elektrycznych ("Hawkin's New Catechism of Electricity", T. Audel & Co., 1896) albo przyczyny szumu na liniach telefonicznych lub telegraficznych. Słowa “bug” w sensie nagłego rujnującego zdarzenia używano już w czasach Shakespeare’a. Samo słowo w tym znaczeniu prawdopodobnie pochodzi z walijskiego (zanglicyzowanego) “bugbear”, oznaczającego różne mityczne potwory.

2 Strona z dziennika komputera Harvard II z opisem usunięcia ćmy z obwodów wraz z przyklejonym owadem.
Admirał Grace Murray Hopper ( )

3 Jeden z “najsławniejszych” błędów w FORTRANie (historia opisana przez Freda Webba na alt.folklore.computers w roku 1990: I worked at Nasa during the summer of The group I was working in was doing preliminary work on the Mission Control Center computer systems and programs. My office mate had the job of testing out an orbit computation program which had been used during the Mercury flights. Running some test data with known answers through it, he was getting answers that were close, but not accurate enough. So, he started looking for numerical problems in the algorithm, checking to make sure his tests data was really correct, etc. After a couple of weeks with no results, he came across a DO statement, in the form: DO 10 I=1.10 This statement was interpreted by the compiler (correctly) as: DO10I = 1.10 The programmer had clearly intended: DO 10 I = 1, 10

4 Najczęstsze błędy podczas programowania w FORTRANie i sposoby zapobiegania im
Literówki w nazwach i nie tylko (np. JI zamiast IJ, “1” zamiast “I” lub “O” zamiast “0” jako indeks tablicy albo w wyrażeniach Rezygnacja z reguły pierwszej litery (zawsze dajemy IMPLICIT NONE). Używanie małych a nie dużych liter (trudno pomylić z cyframi) Pomyłkowe wstawienie zmiennych lub stałych całkowitych aby uzyskać wyrażenie rzeczywiste (np. X=1/6) Czasami pomaga wymóg deklarowania zmiennych Niewspółmierność bloków COMMON w różnych segmentach Bloki COMMON zapisać w plikach I używać instrukcji INCLUDE Niezgodność rozmiarów tablic w różnych segmentach Deklarować dyrektywą PARAMETER stałe używane w wymiarowaniu tablic i zapisać deklaracje w plikach włączanych do źródła przez INCLUDE Wyjście poza 72-gą kolumnę Używać edytorów tekstów z licznikiem kolumn Użycie tablicy w kontekście zmiennej prostej lub odwrotnie Niezgodność listy parametrów formalnych i aktualnych

5 Sposoby odrobaczania programu
Analiza kodu źródłowego Analiza wyników działania programu Diagnostyka użytkownika (drukowanie wyników pośrednich) Użycie opcji kompilatora generujących informację diagnostyczną oraz sprawdzających przekroczenie granic tablic. Użycie odpowiednego programu narzędziowego, debuggera.

6 Sześć zasad odrobaczania.
Doprowadź do tego, żeby błąd był powtarzalny. Zawęż problem do najprostszych przebiegów z najmniejszym zestawem danych, najlepiej takich gdzie wszystkie operacje możesz przeprowadzić na piechotę. Zlokalizuj najmniejszą jednostkę programu, gdzie błąd występuje. Przeprowadź odpowiednio zaplanowane eksperymenty (np., jeżeli program ma obliczyć kąt między trzema atomami rozsądnie jest wybrać najpierw współrzędne które dadzą kąt prosty, potem pełny, potem dowolny. Używaj doświadczenia własnego i innych. Nigdy nie dopuszczaj myśli, że problemu nie rozwiążesz albo że do jego rozwiązania jest potrzebna wiedza magiczna. Więcej w artykule Terence Parr “Learn the Essentials of Debugging”

7 Debuggery do kodów FORTRANowskich
gdb (Linux, darmowy) dbx (AIX i inne systemy; przychodzi z kompilatorem) xdb (AIX; okienkowy) totalview (AIX, UNICOS; okienkowy)

8 Praca z debuggerem gdb Kompilacja z opcją –g (dodaje informację diagnostyczną do kodu wynikowego) Przykład: f77 –g program.f –o program Warto dodać sprawdzanie rozmiarów tablic (opcja fbounds-check), np: f77 –g –fbounds-check program.f –o program Tak skompilowany program można uruchomić z poziomu gdb: gdb program

9 Podstawowe komendy debuggera
break plik.f:nr_linii ustawienie punktu zatrzymania w linii nr_linii pliku źródłowego plik.f clear plik.f:nr_linii usunięcie danego punktu zatrzymania run wykonanie programu do końca lub pierwszego zatrzymania cont wznowienie wykonywania programu po napotkaniu punktu zatrzymania next [liczba_linii] przejście do następnej linii lub wykonanie następnych liczba_linii kodu danego podprogramu bez wliczania linii wywoływanych popdrogramów lub funkcji. step [liczba_linii] przejście do następnej instrukcji lub wykonanie następnych liczba_linii instrukcji programu, włączając linie podprogramów lub funkcji wywoływanych print zmienna drukowanie wartości danej zmiennej. quit wyjście z debuggera.

10 Trochę bardziej zaawansowane ale użyteczne komendy
cd katalog zmiana katalogu roboczego na katalog pwd pokazuje katalog roboczy file prog ładowanie programu prog do debuggera set args arg wprowadzanie argumentów arg do linii polecenia programu list [nr1,nr2] listowanie 10 linii kodu scentrowanych na danej linii (uwaga: kolejne list kontytuuje) albo od linii nr1 do linii nr2. list +[-] listowanie następnych (+) albo poprzednich (-) linii kodu źródłowego. list plik.f:linia listowanie kodu źródłowego z pliku plik.f począwszy od linii linia. info kategoria informacja na temat danej kategorii; np. info break podaje informację o punktach zatrzymania where pokazuje w którym miejscu programu się znajdujemy backtrace where full pokazuje gdzie się znajdujemy oraz drukuje wartości wszystkich backtrace full zmiennych w danym segmencie oraz segmentach wywołujących

11 Pełen opis gdb: http://www.delorie.com/gnu/docs/gdb/gdb.html
set z=wartość nadawanie nowej wartości zmiennej z występującej w aktualnie analizowanym module programu set env zm=wyr Nadawanie wartości wyr zmiennej środowiskowej zm unset env zm anulowanie zmiennej środowiskowej zm show env pokazuje zmienne środowiskowe show path pokazuje ścieżki dostępu where full pokazuje gdzie się znajdujemy oraz drukuje wartości wszystkich zmiennych w danym segmencie oraz segmentach wywołujących watch wyrażenie zatrzymuje program jeżeli wartość wyrażenia wyrażenie zmienia się i drukuje nową wartość (wyrażenie może być nazwą zmiennej) awatch wyrażenie zatrzymuje program jeżeli wyrażenie jest pisane lub czytane rwatch wyrażenie zatrzymuje program, jeżeli wyrażenie jest czytane Pełen opis gdb:

12 Przykład użycia debuggera do śledzenia wykonywania programu titr obliczającego krzywą miareczkowania mocnego kwasu mocną zasadą Źródła FORTRANowskie titr.f czyt_dane.f oblicz_krzywa.f oblicz_ph.f pisz_wyniki.f DIMENSIONS Dane krzywa_dane Wyniki krzywa_wyniki Plik Makefile

13 Przykład sesji debuggera
etoh:~/FORTRAN/DEBUG> gdb titr (gdb) break titr.f:15 Breakpoint 1 at 0x804887b: file titr.f, line 15. (gdb) run Starting program: /big/staff/adam/FORTRAN/DEBUG/titr Breakpoint 1, MAIN__ () at titr.f:15 CALL OBLICZ_KRZYWA(IOUT,CKW,CZ,VKW) Current language: auto; currently fortran (gdb) print ckw $1 = (gdb) next CALL PISZ_WYNIKI(IOUT) (gdb) step pisz_wyniki__ (wyjscie=0x804a050) at pisz_wyniki.f:7 OPEN(WYJSCIE,FILE='krzywa.wyniki',STATUS='UNKNOWN') (gdb) step 3 WRITE(WYJSCIE,'(I3,2x,F5.2,F8.3)') I,OBJZ(I),PH(I) (gdb) cont Continuing. Program exited normally. (gdb)

14 Sprawdzanie przekroczenia rozmiarów tablic
Zmieniamy w pliku DIMENSIONS maksymalną liczbę punktów ze 100 na 10 PARAMETER (MAXPUNKT=10) Kompilujemy bez debuggingu etoh:~/FORTRAN/DEBUG> make f77 -c titr.f f77 -c czyt_dane.f f77 -c oblicz_krzywa.f f77 -c oblicz_ph.f f77 -c pisz_wyniki.f f77 -o titr titr.o czyt_dane.o oblicz_krzywa.o oblicz_ph.o pisz_wyniki.o etoh:~/FORTRAN/DEBUG> ./titr Program pozornie się wykonał ale plik krzywa.wyniki zawiera tylko nagłówek etoh:~/FORTRAN/DEBUG> more krzywa.wyniki Punkt VZ pH

15 Teraz kompilujemy z –fbounds-check –g
etoh:~/FORTRAN/DEBUG> make -f Makefile-debug f77 -c -fbounds-check -g titr.f f77 -c -fbounds-check -g czyt_dane.f f77 -c -fbounds-check -g oblicz_krzywa.f f77 -c -fbounds-check -g oblicz_ph.f f77 -c -fbounds-check -g pisz_wyniki.f f77 -o titr -fbounds-check -g titr.o czyt_dane.o oblicz_krzywa.o oblicz_ph.o pisz_wyniki.o Po uruchomieniu od razu widać, gdzie jest problem etoh:~/FORTRAN/DEBUG> ./titr Subscript out of range on file line 12, procedure czyt. Attempt to access the 21-th element of variable vz. Abort

16 Zatrzymanie C Czytanie danych wejsciowych IMPLICIT NONE
SUBROUTINE CZYT_DANE(WEJSCIE,STKW,STZ,OBJKW) C Czytanie danych wejsciowych IMPLICIT NONE INCLUDE 'DIMENSIONS' INTEGER WEJSCIE,I,NPUNKT REAL*8 STKW,STZ,OBJKW REAL*8 VZ(MAXPUNKT),PH(MAXPUNKT) COMMON /KRZYWA/ VZ,PH,NPUNKT OPEN(WEJSCIE,FILE='krzywa.dane',STATUS='OLD') READ(WEJSCIE,*) NPUNKT,STKW,STZ,OBJKW READ(WEJSCIE,*) (VZ(I),I=1,NPUNKT) CLOSE(WEJSCIE) RETURN END Zatrzymanie

17 Podobne informacje dostajemy uruchamiając program z poziomu debuggera
etoh:~/FORTRAN/DEBUG> gdb titr (gdb) run Starting program: /big/staff/adam/FORTRAN/DEBUG/titr Subscript out of range on file line 12, procedure czyt. Attempt to access the 21-th element of variable vz. Program received signal SIGABRT, Aborted. 0x b in raise () from /lib/tls/libc.so.6 Możemy wtedy zapytać dokładnie gdzie błąd nastąpił (gdb) where #0 0x b in raise () from /lib/tls/libc.so.6 #1 0x40093fa2 in abort () from /lib/tls/libc.so.6 #2 0x f in sig_die () from /usr/lib/libg2c.so.0 #3 0x40027c94 in s_rnge () from /usr/lib/libg2c.so.0 #4 0x080489ea in czyt_dane__ (wejscie=0x804a04c, stkw=0xbffffc10, stz=0xbffffc08, objkw=0xbffffc00) at czyt_dane.f:12 #5 0x b in MAIN__ () at titr.f:12 #6 0x08048dd6 in main ()

18 Można też uzyskać pełną informację, łącznie z wartościami zmiennych
(gdb) where full #0 0x b in raise () from /lib/tls/libc.so.6 No symbol table info available. #1 0x40093fa2 in abort () from /lib/tls/libc.so.6 #2 0x f in sig_die () from /usr/lib/libg2c.so.0 #3 0x40027c94 in s_rnge () from /usr/lib/libg2c.so.0 #4 0x080489ea in czyt_dane__ (wejscie=0x804a04c, stkw=0xbffffc10, stz=0xbffffc08, objkw=0xbffffc00) at czyt_dane.f:12 __g77_impdo_0 = 10 __g77_cilist_1 = {err = 0, unit = 1, end = 0, format = 0x0, rec = 0}

19 ph = {0 <repeats 20 times>}
npunkt = 31 vz = {1, 2, 3, 4, 5, 6, 7, 8, 9, , , , , , , , 10, 10.01, , 10.1} ph = {0 <repeats 20 times>} #5 0x b in MAIN__ () at titr.f:12 n = 31 inp = 1 iout = 2 ckw = cz = vkw = 10 #6 0x08048dd6 in main () No symbol table info available.

20 Dlaczego błąd nie był sygnalizowany bez opcji –fbounds-check, natomiast program nie wydrukował wyników ? Kompilujemy tylko z opcją –g etoh:~/FORTRAN/DEBUG> make -f Makefile-debug1 f77 -c -g titr.f f77 -c -g czyt_dane.f f77 -c -g oblicz_krzywa.f f77 -c -g oblicz_ph.f f77 -c -g pisz_wyniki.f f77 -o titr -g titr.o czyt_dane.o oblicz_krzywa.o oblicz_ph.o pisz_wyniki.o

21 Kompilujemy tylko z opcją –g
etoh:~/FORTRAN/DEBUG> make -f Makefile-debug1 f77 -c -g titr.f f77 -c -g czyt_dane.f f77 -c -g oblicz_krzywa.f f77 -c -g oblicz_ph.f f77 -c -g pisz_wyniki.f f77 -o titr -g titr.o czyt_dane.o oblicz_krzywa.o oblicz_ph.o pisz_wyniki.o Uruchamiamy z gdb ustawiając zatrzymanie w pisz_wyniki.f etoh:~/FORTRAN/DEBUG> gdb titr (gdb) break pisz_wyniki.f:1 Breakpoint 1 at 0x8048aec: file pisz_wyniki.f, line 1. (gdb) run Starting program: /big/staff/adam/FORTRAN/DEBUG/titr Breakpoint 1, pisz_wyniki__ (wyjscie=0x804864c) at pisz_wyniki.f:1 SUBROUTINE PISZ_WYNIKI(WYJSCIE) Current language: auto; currently fortran

22 Drukujemy pełną informację
(gdb) where full #0 pisz_wyniki__ (wyjscie=0x804864c) at pisz_wyniki.f:1 i = npunkt = objz = (1, 2, 3, 4, 5, 6, 7, 8, 9, , , , , , , , 10, 10.01, , 10.1) ph = ( , , , , , , , , , , , , , , , , 7, , , )

23 #1 0x08048868 in MAIN__ () at titr.f:16
inp = 1 iout = 2 ckw = cz = vkw = 10 vz = (1, 2, 3, 4, 5, 6, 7, 8, 9, , , , , , , , 10, 10.01, , 10.1) ph = ( , , , , , , , , , , , , , , , , 7, , , ) #2 0x08048c76 in main () No symbol table info available.

24 Taka wartość zmiennej NPUNKT (w pisz_wyniki. f) lub N (w titr
Taka wartość zmiennej NPUNKT (w pisz_wyniki.f) lub N (w titr.f) jest wynikiem nadpisania jej przez pierwszy element tablicy PH wykraczający poza zadeklarowany rozmiar tablicy. Zmienna NPUNKT lub N sąsiadje z tablicą PH w obszarze wspólnym KRZYWA: REAL*8 VZ(MAXPUNKT),PH(MAXPUNKT) COMMON /KRZYWA/ VZ,PH,NPUNKT Błąd ten nastąpił w podprogramie oblicz_krzywa.f, gdzie jest wypełniana tablica PH. Jeżeli podejrzewamy, że problem jest ze zmienną NPUNKT, możemy wydrukować jej wartość bez zrzucania całego zestawu zmiennych w danym punkcie programu. (gdb) print npunkt $1 =

25 Zmianę wartości n możemy też śledzić przy pomocy komendy watch
(gdb) break titr.f:1 Breakpoint 1 at 0x : file titr.f, line 1. (gdb) run Starting program: /big/staff/adam/FORTRAN/DEBUG/titr Breakpoint 1, MAIN__ () at titr.f:1 PROGRAM TITR Current language: auto; currently fortran

26 (gdb) watch n Hardware watchpoint 2: n (gdb) cont Continuing. Old value = 0 New value = 31 0x4002ffc7 in l_read () from /usr/lib/libg2c.so.0 Old value = 31 New value = oblicz_krzywa__ (wyjscie=0x , stkw=0xbffffc10, stz=0xbffffc08, objkw=0xbffffc00) at oblicz_krzywa.f:13 ENDDO

27 Użyteczne warianty wywoływania gdb
Analiza zrzutu pamięci (coredump) programu który się “wywalił” Zwykle zrzut jest zapisany w pliku core. Przykładowo po wywołaniu gdb prog core gdb zachowa się tak, jakby program prog był uruchomiony z poziomu debuggera i zatrzymał się wskutek błędu, zatem można prowadzić analizę używając where, print, itp. Kolejność argumentów nie obowiązuje jeżeli prog poprzedzimu –e a core –c. Debugging już uruchomionego programu gdb prog nr_procesu Gdzie prog jest nazwą pliku wykonywalnego a nr_procesu numerem procesu odpowiadającego “chodzącemu” programowi. Specyfikowanie katalogów, gdzie znajdują się pliki źródłowe gdb –d katalog prog


Pobierz ppt "Odrobaczanie (debugging) programu"

Podobne prezentacje


Reklamy Google