• Nie Znaleziono Wyników

Sposoby wykrywania i usuwania błędów

N/A
N/A
Protected

Academic year: 2021

Share "Sposoby wykrywania i usuwania błędów"

Copied!
14
0
0

Pełen tekst

(1)

Sposoby wykrywania i

usuwania błędów

(2)

Mylić się jest rzeczą ludzką

2

Typy błędów:

błędy specyfikacji: źle określone wymagania

błędy projektowe: nieodpowiednie struktury danych i algorytmybłędy kodu: powstają na etapie realizacji projektu przy pomocy

wybranego narzędzia programistycznego

Etapy debugowania, poprawiania programu:

testowanie: znalezienie błędu

lokalizacja: zidentyfikowanie błędnego kodukorekta: poprawienie błędu

weryfikacja: sprawdzenie czy poprawka działa

Program z błędem:

W pliku debug1.c znajduje się funkcja sort, która ma sortować

struktury typu item metodą bąbelkową. Niestety po

(3)

Sposoby testowania

3 Przeglądanie kodu

Podstawowym sposobem wykrywania błędów jest przeglądanie kodu. Najlepiej, gdy nasz kod przejrzy inna osoba. Do wykrywania błędów składniowych możemy użyć kompilatora:

gcc -Wall -pedantic -ansi -o debug1 debug1.c

Oprzyrządowanie kodu

Oprzyrządownie polega na dodawaniu nowego kodu do testowanego programu w celu zebrania jak największej liczby informacji o

programie. Wykorzystuje się do tego preprocesor C, pozwalający

decydować podczas kompilacji, czy dołączyć kod wykorzystywany do debugowania. Np.:

#ifdef DEBUG

printf("debug: x=%d\n", x); #endif

powyżej printf wykona się, gdy program będzie skompilowany z

(4)

4

cd

Sposoby testowania

Oprzyrządowanie kodu bez ponownej kompialcji

Wadą poprzedniego rozwiązania była konieczność ponownej

kompilacji przed każdym debugowaniem. Alternatywnymi sposobami umożliwiania debugowania kodu przez użytkownika są:

Program gdb

gdb jest programem umożliwiającym śledzenie wykonywania innych

programów. Śledzony program powinien być skompilowany z opcją

-g by do kodu wynikowego dołączyć informacje istotne dla

debugera. gcc -g -o debug3 debug3.c gdb debug3

komenda (gdb) help wyświetla dostępne komendy

(patrz: man gdb i info gdb).

 Obsługa przez debugowany program opcji -d podawanej z linii

komend (trzeba ją oprogramować samemu)

 Użycie w programie możliwości rejestracji zachowania programu przez funkcję syslog (patrz man 3 syslog)

(5)

5

Program

gdb

gdb uruchamianie

Rozpoczynamy wykonanie programu komendą (gdb)run. Argumenty

polecenia (gdb)run zostaną przekazane testowanemu programowi.

W naszym przypadku pojawi się błąd segmentacji wraz z linią, w której po raz pierwszy ten błąd wystąpił.

gdb śledzenie stosu

Komenda (gdb)backtrace pozwala śledzić stos wywołań aż do

miejsca, w którym jesteśmy. Używane do programów z większą liczbą wywołań podprogramów i funkcji.

gdb badanie zmiennych

Wypisywania wartości zmiennych: (gdb)print zmienna.

Rezultaty są przechowywane w pseudozmiennych $<liczba>,

ostatni rezultat to $, a przedostatni $$.

Sprawdzamy (gdb)print j, problem sprawiło: a[4]=a[4+1].

Spróbuj: (gdb)print a[$-1].klucz lub print a[3]

(6)

6

Program

gdb

cd

gdb listing programu

Polecenie (gdb)list wypisuje fragment programu wokół bieżącej

pozycji. Widzimy, że zmienna j nie powinna przyjmować wartości 4.

Zmieńmy więc linię 23. na następującą:

/* 23 */ for( j=0; j<n-1; j++ ) {

Po kompilacji i uruchomieniu (patrz debug4.c) program działa ale wynik nie jest niepoprawny. Sprawdźmy co robi w trakcie dziłania.

gdb puntky przerwania

gdb posiada komendy pozwalającę wstawiać i kontrolować tzw.

punkty przerwania. Zobacz (gdb)help breakpoint.

My wstawimy punkt przerwania w linii 21.: (gdb)break 21

uruchomimy program (gdb)run. Program zatrzyma się w na linii 21.

Wypisujemy stan tablicy: (gdb)print tablica[0]@5 i

(7)

7

Program

gdb

jeszcze

Wypisanie stanu tablicy za każdym razem, gdy program się zatrzyma:

(gdb)display tablica[0]@5. Używając komendy (gdb)

commands. ustalamy, że program ma wykonać cont za każdym

razem, gdy dojdzie do bieżącego punktu przerwania.

Analiza zachowania programu doprowadza nas do wniosku, że zewnętrzna pętla nie wykonuje się tyle razy ile powinna.

Podejrzewamy, że winna temu jest linia 31. Spróbujmy to sprawdzić.

gdb łatanie

Łatą nazywamy kod, który musimy dodać do programu aby działał

poprawnie. Stosując punkty przerwania możemy sprawdzić łatę zanim zmienimy kod źródłowy.

Wyłączamy poprzednio ustawiony punkt przerwania i związane z nim wyświetlanie: (gdb)disable break 1 i

(gdb)disable display 1. Ustawiamy przerwanie w linii 31. i

kojarzymy z nim komendy: set variable n = n+1 i cont.

(8)

8

Program

patch

Dystrybucja nowych wersji programów jest kłopotliwa (zwłaszcza, gdy dostarczamy wersje binarne). Oprogramowanie typu Open

Source znacznie ułatwia dystrybucję nowych wersji. Zamiast

udostępniać nową wersję w pełnej (wielo-MB) postaci, udostępnia się jedynie różnice pomiędzy wersjami. Program diff służy do

tworzenia plików zawierających różnice między źródłami wersji.

diff plik1.txt plik2.txt > ró?nice.txt

Łatanie programu, tj. uaktualnianie źródeł można wykonać tak:

patch plik1.txt ró?nice.txt Odwracanie tego procesu:

patch -R plik1.txt ró?nice.txt

Zadania:

1. Zrobić łatę/łaty dla przykładu z gdb

2. Zrobić łatę do programu składającego się z wielu plików -

(9)

9

Testy pokrycia

Jedynym sposobem potwierdzenia poprawności programu jest

udowodnienie, że dla każdej możliwej wartości danych wejściowych program zwraca poprawny wynik. Dla większości programów, z

wyjątkiem najprostszych, jest to zadanie tak skomplikowane, że praktycznie jest niewykonalne.

Kompromisem nieograniczającym zakresu testów są tzw. testy

pokrycia. Idea testów pokrycia polega na próbie oszacowania, jaka część kodu została wykonana podczas testów. Jeżeli w czasie testów wykonana została każda część programu, ich wyniki uznamy za

bardziej godne zaufania.

Istnieją trzy rodzaje testów pokrycia:  Pokrycie instrukcji

 Pokrycie rozgałęzień programu  Pokrycie danych

(10)

10

Pokrycie instrukcji

Pokrycie instrukcji polega na sprawdzeniu czy podczas testów została wykonana każda linijka programu. Pokrycie instrukcji ma wadę: nie bierze się w nim pod uwagę wzajemnego oddziaływania części programu. Przykład:

1 :int f(int a,int b){ 2 : int r = 1; 3 : if(a>0){ 4 : r = 0; 5 : }; 6 : if(b>0){ 7 : r = 3/r; 8 : } 10: return r; 11:} Linie 1, 2, 3, 6 i 10 są testowane

zawsze. Aby pokryć linię 4 należy

przetestować f(1,0), natomiast by

pokryć linię 7, f(0,1). Teraz nasz

test pokrywa już wszystkie instrukcje programu.

Co się jednak stanie gdy sprawdzimy wywołanie f(1,1)?

(11)

11

Pokrycie rozgałęzień i danych

Test pokrycia rozgałęzień programu polega na rozważeniu

wszystkich możliwych ścieżek działań programu. Liczba możliwych ścieżek programu znacznie wzrasta w miarę dodawania pętli i

instrukcji warunkowych. Powoduje to także wzrost liczby testów do ich pełnego pokrycia.

Test pokrycia danych obejmuje testowanie każdej możliwej kombinacji użytych danych.

Istnieje kilka narzędzi do badania stopnia pokrycia badanego programu za pomocą przeprowadzonych testów. Narzędzia te

pracują na zasadzie zwbogacania testowanego programu w trakcie kompilacji. Dodatkowy kod służy do gromadzenia informacji o tym, które instrukcje były wykonywane i jak często.

Ponieważ narzędzia te działają na poziomie instrukcji, kod programu powinien być tak napisany by każda linia zawierała najwyżej jedną istrukcję. Złym rozwiązaniem jest umieszczanie instrukcji

warunkowej w jednej linii lub stosowanie makr zawierających wyrażenia warukowe.

(12)

12

Narzędzie

gcov

gcov jest narzędziem do testowania pokrycia instrukcji programu.

Aby korzystać z gcov, należy przygotować specjalną wersję badanej

aplikacji (podobnie jak dla gdb). Do przygotowania kodu musimy użyć

kompilatora C w wersji GNU ze specjalnymi opcjami linii poleceń:-fprofile-arcs zmusza kompilator do umieszczania w

testowanym programie dodatkowego kodu, pozwalającego

rejestrować, która instrukcja jest wykonywana. Informacja taka będzie zapisywana w pliku o nazwie takiej jak plik źródłowy z końcówką .da

-ftest-coverage prócz pliku z kodem obiektowym (.o)

powstaną pliki o końcówkach .bb i .bbg, zawierające zapis

struktury rozgałęzień kodu źródłowego. Używane są przez gcov do

tworzenia mapy działania programu.

-fbranch-probabilities opcja ta powoduje optymalizację

(13)

Narzędzie

gcov

13

przykład

W katalogu testy znajduje się przykładowa aplikacja obliczająca wyrażenia arytmetyczne zadane w Odwrotnej Notacji Polskiej. Aplikacja składa się z kilku plików zawierających funkcje

zewnętrzne, pliku Makefile oraz plików test[0-6] zawierających testowe wyrażenia.

Przykładowy przebieg testów:  Kompilacja aplikacji:

$ make

 Wykonanie testów:

$ make test

 Wykonanie analiz pokrycia:

$ make gcov

 Wykonanie kasowania liczników:

$ make clean_da

Analizując testy aplikacji należy szczególną uwagę zwrócić na:

 Opcje polecenia gcov

 Wpływ plików *.da na

zawartość plików *.c.gcov

 Analizę rozgałęzień kodu

(patrz opcja -b polecenia gcov

i instrukcje rozgałęziające: if, case, for, while)

(14)

14

Testowanie wydajności

Ważnym aspektem testowania jest wydajność. Aplikacja prócztego, że musi działać poprawnie musi być użyteczna, czyli oddawać wyniki w rozsądnym czasie. Stąd ważne jest znajdowanie w programie

takich miejsc, w których traci się najwięcej czasu.

Narzędziem, które może nam pomóc w testowaniu wydajności jest

gprof. Aby przygotować kod programu dla gprof należy go

skompilować z opcją -pg, następnie uruchomić program i po nim

wywołać gprof z nazwą programu. Przykładowe wywołania w

plikach Makefile w katalogach testy i testy2.

Po uruchomieniu programu powstaje plik gmon.out, zawierający

zapis profilu działania. Program w trakcie działania zapisał w nim wyniki pomiarów czasu spędzonego w każdej z funkcji.

Program gprof może gromadzić dane z wielu uruchomień badanego

programu. Aby skorzystać z tej możliwości, należy użyć opcji -s w

wywołaniu gprof. Informacja o profilu będzie wówczas gromadzona

Cytaty

Powiązane dokumenty

Wartości sił wewnętrznych oraz ugięć sprężystych chwilowych wyznaczamy zgodnie z zasadami (regułami) mechaniki budowli. SCHEMAT STATYCZNY MOMENT ZGINAJĄCY

Analogicznie, jak dla instrukcji czytania, instrukcja pisania odnosi się do listy wyrażeń wypisanych na wyjście (ekran, plik,

Powierzchniowa forma tych problemów sugeruje błędną ścieżkę rozwiązań, prawdo- podobnie więc osoba badana szacuje swoje „poczucie ciepła” na podstawie złej repre-

murowane drewniane betonowy / papa dostateczny dostateczny dostateczny dobry brak dostateczny 557,30 1 nie nie..

3-5-punktów -wszystkie elementy treści podjęte ale ilośc błędów uniemożliwia zrozumienie informacji przez czytelnika. 0-2-punkty- informacja o spotkaniu zawarta, ale

P280 Stosować rękawice ochronne/ odzież ochronną/ ochronę oczu/ ochronę twarzy/ ochronę słuchu.. Spłukać skórę pod

P280 Stosować rękawice ochronne/ odzież ochronną/ ochronę oczu/ ochronę twarzy.. NIE

P210 Przechowywać z dala od źródeł ciepła, gorących powierzchni, źródeł iskrzenia, otwartego ognia i innych źródeł zapłonu.. P273 Unikać uwolnienia