Laboratorium zerowe: O bª dach w trakcie pisania programów i metodach radzenia sobie z nimi.

Podobne dokumenty
ANALIZA NUMERYCZNA. Grzegorz Szkibiel. Wiosna 2014/15

1. Wprowadzenie do C/C++

1. Wprowadzenie do C/C++

Wska¹niki, tablice dynamiczne wielowymiarowe

1 Metody iteracyjne rozwi zywania równania f(x)=0

Lab. 02: Algorytm Schrage

1 Bª dy i arytmetyka zmiennopozycyjna

Ukªady równa«liniowych

Funkcje, wielomiany. Informacje pomocnicze

A = n. 2. Ka»dy podzbiór zbioru sko«czonego jest zbiorem sko«czonym. Dowody tych twierdze«(elementarne, lecz nieco nu» ce) pominiemy.

Bash i algorytmy. Elwira Wachowicz. 20 lutego

ARYTMETYKA MODULARNA. Grzegorz Szkibiel. Wiosna 2014/15

Arytmetyka zmiennopozycyjna

P tle. Rozdziaª Wst p. 4.2 P tle P tla for(...);

Lekcja 9 - LICZBY LOSOWE, ZMIENNE

Metody numeryczne. Wst p do metod numerycznych. Dawid Rasaªa. January 9, Dawid Rasaªa Metody numeryczne 1 / 9

Vincent Van GOGH: M»czyzna pij cy li»ank kawy. Radosªaw Klimek. J zyk programowania Java

Lekcja 12 - POMOCNICY

2 Liczby rzeczywiste - cz. 2

Metodydowodzenia twierdzeń

Materiaªy do Repetytorium z matematyki

Lekcja 9 Liczby losowe, zmienne, staªe

WST P DO TEORII INFORMACJI I KODOWANIA. Grzegorz Szkibiel. Wiosna 2013/14

Przetwarzanie sygnaªów

Dokªadna arytmetyka liczb rzeczywistych w j zyku Python

Listy Inne przykªady Rozwi zywanie problemów. Listy w Mathematice. Marcin Karcz. Wydziaª Matematyki, Fizyki i Informatyki.

Liczby zmiennoprzecinkowe

ARYTMETYKA MODULARNA. Grzegorz Szkibiel. Wiosna 2014/15

Relacj binarn okre±lon w zbiorze X nazywamy podzbiór ϱ X X.

Lekcja 6 Programowanie - Zaawansowane

Informacje pomocnicze

x y x y x y x + y x y

ARYTMETYKA MODULARNA. Grzegorz Szkibiel. Wiosna 2014/15

X WARMI SKO-MAZURSKIE ZAWODY MATEMATYCZNE 18 maja 2012 (szkoªy ponadgimnazjalne)

Ekonometria - wykªad 8

1 Granice funkcji wielu zmiennych.

Programowanie wspóªbie»ne

Metody dowodzenia twierdze«

Czy funkcja zadana wzorem f(x) = ex e x. 1 + e. = lim. e x + e x lim. lim. 2 dla x = 1 f(x) dla x (0, 1) e e 1 dla x = 1

ARYTMETYKA MODULARNA. Grzegorz Szkibiel. Wiosna 2014/15

Janusz Adamowski METODY OBLICZENIOWE FIZYKI Zastosowanie eliptycznych równa«ró»niczkowych

Ekonometria. wiczenia 1 Regresja liniowa i MNK. Andrzej Torój. Instytut Ekonometrii Zakªad Ekonometrii Stosowanej

Programowanie i struktury danych 1 / 44

Caªkowanie numeryczne - porównanie skuteczno±ci metody prostokatów, metody trapezów oraz metody Simpsona

1 Klasy. 1.1 Denicja klasy. 1.2 Skªadniki klasy.

Przekroje Dedekinda 1

Ekstremalnie fajne równania

Wst p do sieci neuronowych 2010/2011 wykªad 7 Algorytm propagacji wstecznej cd.

WST P DO TEORII INFORMACJI I KODOWANIA. Grzegorz Szkibiel. Wiosna 2013/14

Uczenie Wielowarstwowych Sieci Neuronów o

Macierze i Wyznaczniki

Równania ró»niczkowe I rz du (RRIR) Twierdzenie Picarda. Anna D browska. WFTiMS. 23 marca 2010

XVII Warmi«sko-Mazurskie Zawody Matematyczne

Macierze. 1 Podstawowe denicje. 2 Rodzaje macierzy. Denicja

wiczenie 1 Podstawy j zyka Java. Instrukcje warunkowe

Programowanie wspóªbie»ne

Twierdzenie Wainera. Marek Czarnecki. Warszawa, 3 lipca Wydziaª Filozoi i Socjologii Uniwersytet Warszawski

Edyta Juszczyk. Akademia im. Jana Dªugosza w Cz stochowie. Lekcja 1Wst p

punkcie. Jej granica lewostronna i prawostronna w punkcie x = 2 wynosz odpowiednio:

Optymalizacja R dlaczego warto przesi ± si na Linuxa?

Lekcja 5 Programowanie - Nowicjusz

Macierze i Wyznaczniki

Funkcje wielu zmiennych

Modele wielorównaniowe. Problem identykacji

JAO - J zyki, Automaty i Obliczenia - Wykªad 1. JAO - J zyki, Automaty i Obliczenia - Wykªad 1

wiczenie nr 3 z przedmiotu Metody prognozowania kwiecie«2015 r. Metodyka bada«do±wiadczalnych dr hab. in». Sebastian Skoczypiec Cel wiczenia Zaªo»enia

Rekurencyjne struktury danych

Zadania z kolokwiów ze Wst pu do Informatyki. Semestr II.

1 a + b 1 = 1 a + 1 b 1. (a + b 1)(a + b ab) = ab, (a + b)(a + b ab 1) = 0, (a + b)[a(1 b) + (b 1)] = 0,

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Przykªadowe tematy z JiMP

6. Pętle while. Przykłady

O pewnym zadaniu olimpijskim

Podziaª pracy. Cz ± II. 1 Tablica sortuj ca. Rozwi zanie

Zestaw 1 ZESTAWY A. a 1 a 2 + a 3 ± a n, gdzie skªadnik a n jest odejmowany, gdy n jest liczb parzyst oraz dodawany w przeciwnym.

Podstawy Programowania C++

Zbiory i odwzorowania

Rozdziaª 13. Przykªadowe projekty zaliczeniowe

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Ciaªa i wielomiany. 1 Denicja ciaªa. Ciaªa i wielomiany 1

Interpolacja Lagrange'a, bazy wielomianów

Lekcja 3 Banki i nowe przedmioty

AM II /2019 (gr. 2 i 3) zadania przygotowawcze do I kolokwium

Rozwi zania klasycznych problemów w Rendezvous

Podstawy JavaScript. Dawid Poªap. Dawid Poªap Technologia informacyjna Grudzie«, / 13

Programowanie wspóªbie»ne

ARYTMETYKA MODULARNA. Grzegorz Szkibiel. Wiosna 2014/15

Programowanie i struktury danych

CAŠKOWANIE METODAMI MONTE CARLO Janusz Adamowski

Wybrane poj cia i twierdzenia z wykªadu z teorii liczb

Metody numeryczne i statystyka dla in»ynierów

ˆ tablice statyczne (o staªej ilo±ci elementów) ˆ tablice dynamiczne (o zmiennej ilo±ci elementów) 7.1 Tablice jednowymiarowe statyczne

Metody numeryczne i statystyka dla in»ynierów

Zagadnienia na wej±ciówki z matematyki Technologia Chemiczna

przewidywania zapotrzebowania na moc elektryczn

Kompilowanie programów

1 Przypomnienie wiadomo±ci ze szkoªy ±redniej. Rozwi zywanie prostych równa«i nierówno±ci

Indeksowane rodziny zbiorów

c Marcin Sydow Przepªywy Grafy i Zastosowania Podsumowanie 12: Przepªywy w sieciach

Interpolacja funkcjami sklejanymi

Transkrypt:

Laboratorium zerowe: O bª dach w trakcie pisania programów i metodach radzenia sobie z nimi. March 4, 2015 Abstract Poni»szy tekst zawiera podstawy korzystania z debuggera GDB oraz zawiera opis najcz stszych problemów i bª dów pojawiaj cych si na laboratoriach oraz o sposobach radzenia sobie z nimi. W pierwszej kolejno±ci nale»y pobra szablon C++ do zadania i zapozna si z jego zawarto±ci. Po rozpakowaniu w katalogu powinny si znale¹ nast puj ce pliki: main.cpp - gªówny plik, zawieraj cy przykªady opisane poni»ej. Ten plik b dziemy modykowa. Makele - skrypt który b dziemy wykorzystywa do kompilacji programu. plot.plt - skrypt gnuplota, za pomoc którego b dziemy generowa wykresy. utils/imnmath.hpp plik z funkcjami pomocniczymi przydatnymi podczas pisania programów na laboratorium. Otwieramy konsol i przechodzimy do katalogu w którym znajduje si gªówny katalog szablonu. Poni»ej znajduje si opis problemów, które mo»na napotka podczas pisania programów oraz sposobie radzenia sobie z nimi za pomoc debuggera GDB. 1 Porównanie dokªadno±ci oat i double. Kompilujemy program za pomoc skryptu makele za komend make r e l e a s e nast pnie uruchamiamy program:. / lab Ju» na wst pie naszym oczom powinien sie ukaza bª d segmentation fault. Bez w tpienia problem znajduje si w funkcji problem1(), gdy» jej zakomentowanie nie powoduje generowania si bª du. Najprostszym sposobem szukania bª dów jest metoda: komentowania poszczególnych fragmentów kodu wraz z wykorzystaniem instrukcji printf czy cout. My skorzystamy jednak z debuggera gdb do znalezienia bª du. W pierwszej kolejno±ci nale»y uruchomi program gdb. W tym celu uruchamiamy program za pomoc komendy gdb Nast pnie podajemy nazw pliku który chcemy debugowa : 1

f i l e lab Uruchamiamy program: GDB powinien zako«czy program ale oprócz bª du: segmentation fault nie podaje»adnych pomocnych informacji. Wszystko dlatego,»e nasz program zostaª skompilowany bez opcji debugowania. Skompilujmy nasz program w trybie debugowania. make c l e a n // ( program zapyta o zakonczenie poprzedniego zadania wciskamy "y ") Tym razem program pokazuje, gdzie jest nasz problem: prosz przeczyta dokªadnie komunikat zwrócony przez gdb, gdy» jeszcze do ko«ca nie wiadomo na czym ten problem polega. Widzimy - z komunikatu,»e problemem staje si zapis do tablicy mdata. Za pomoc komendy print mo»emy wypisa warto±ci zmiennych w obecnym konteksie w ktorym gdb wykryª problem. p r i n t i // lub (p i ) wypisze obecna wartosc zmiennej i Zauwa»my,»e wynosi ona i=200, tym czasem rozmiar tablicy wynosi 200 przy czym numeracja C++/C zaczyna sie od zera, zatem ostatni mo»liwy wskaznik to 199. Zatem nasz program wychodzi poza obszar zaalokowanej tablicy. GDB pozwala równie» na wypisywanie zawarto±ci tablicy: p r i n t mdata [ 1 9 9 ] @3 // wypisze o s t a t n i e t r z y elementy macierzy mdata z w iersza 199. Wi cej informacji o wykorzystaniu GDB w kontekscie tablic wielowymiarowych znajd Pa«stwo na stronie: https: //sourceware.org/gdb/onlinedocs/gdb/arrays.html. Prosz spróbowa wywoªa komend : p r i n t mdata [ 2 0 0 ] @3 GDB powinien zwróci komunikat o wyj±ciu poza dozwolony obszar pami ci. Widzimy zatem,»e nasza p tla wychodzi poza obszar zaalokowanej pami ci. Przyczyn tego musi by zatem linijka f o r ( i n t i = 0 ; i <= 200 ; i++) zmie«my j na: f o r ( i n t i = 0 ; i < 200 ; i++) skompilujmy program make c l e a n Nast pnie komenda make spowoduje wygenerowanie wykresu problem1.png. Warto zwróci uwag na ró»nic w wynikach otrzymywanych przez zmienne double i oat. 2

2 Porównywanie liczb zmienno przecinkowych W tym przypadku b dziemy bada liczb iteracji potrzebnych do uzbie»nienia równania rekurencyjnego a n+1 := an, gdzie n oznacza indeks iteracji. Granica takiego szeregu jest znana i wynosi 1 dla a 0 > 0 przy n +, przy czym a 0 oznacza warto± pocz tkow. W problemach numerycznych niesko«czone sumy obcina si do okre±lonej warto±ci n np. n max = 1000, ze wzgl du na sko«czon precyzj numeryczn. Interesuje nas dla jakich warto±ci n dwa ci gi a n (z a 0 = 20) i b n (z b 0 = 1 20 ) zbiegn si do 1. Wiemy,»e w granicy gdy n = +, musz by sobie równe, jednak ze wzgl du na sko«czon precyzj liczb double spodziewamy si osi gn znak równo±ci, po sko«czonej liczbie iteracji do tego celu sprawdzamy ich równo± za pomoc wyra»enia if( a == b). Prosz zakomentowa funkcje problem1 i odkomentowac funkcje problem2. Skompilowa i uruchomic program: Prosz zauwa»y,»e program przy kompilacji zwróci warning dotycz cy porównywania zmiennych double. Nasz program uruchamia si ale ju» na starcie wypisuje do konsoli,»e a = 20 a b = 0. W celu wykrycia bª du wykorzystamy mo»liwo±ci debugera gdb. Skorzystamy z funkcji breakpoint, dzi ki której mo»emy wskaza debugerowi w którym miejscu dziaªania programu program ma si zatrzyma, a nast pnie mo»emy skorzysta z funkcji print, aby wypisa warto±ci zmiennych w tym miejscu programu. Dodawanie breakpointu odbywa si za pomoc komendy break (lub b) w konsoli GDB (wi cej informacji np http://www.unknownroad.com/rtfm/gdbtut/gdbbreak.html). Dodajmy breakpoint, który zatrzyma program w pliku main.cpp w linijce zaraz przed p tl for (w szablonie powinna to by linijka 42). Komenda GDB jest nast puj ca: break main. cpp : 4 2 Informacje o obecnie u»ywanych breakpointach wypisuje funkcja i n f o break Uruchamiamy program Program powinien si zatrzyma na utworzonym breakpointcie. Wypiszmy teraz warto± zmiennych a i b. p r i n t a p r i n t b Widzimy zatem,»e zmienna b ju» o pocz tku wynosi zero. Jest to standardowy problem, gdzie przy dzieleniu zmiennych typu integer 1/20 wynik jest obcinany do zmiennych typu int. Zatem w przestrzeni liczb caªkowitych 1/20 = 0. Aby ten problem naprawi zmie«my linijk double b = 1/20; na np. double b = 1. 0 / 2 0 ; // albo double b = 1. 0 / 2 0. 0 albo double b = 1 / 2 0. 0. Skompilujmy program i uruchommy go od pocz tku: Program ponownie zatrzyma si na ustawionym breakpointcie. Mo»emy ponownie wypisa warto± b: 3

p r i n t b Powinna by ona rózna od zera. Aby przej± dalej wpisujemy: continue // ( lub c ) Kiedy dany breakpoint nie jest ju» nam potrzebny mo»emy do wyª czy d i s a b l e albo usun d e l e t e numer_breakpointu numer_breakpointu Numer breakpointu zwróci nam funkcja i n f o breakpoint Zauwa»my teraz,»e mimo i» a i b po wypisaniu pokazuje 1 waek if (a == b) nie jest speªniony. Dzieje si tak dlatego,»e w rzeczywisto±ci zmienne a i b ró»ni si o bardzo maª warto±. Aby przekona si jak bardzo maªa jest ta ró»nica wykorzystajmy breakpoint z instrukcj wakow. Poni»sza instrukcja zatrzyma program w linijce 50 (je±li zmienna i b dzie wynosi 50). Linijka 50 mo»e si ró»ni w Pa«stwa przypadku wa»ne jest, aby znajdowaªa si ona wewn trz p tli for (mo»e by np. na wysoko±ci instrukcji if( a == b ) break;) break main. cpp : 5 0 i f i == 50 Uruchamiamy program: Je»eli breakpoint zostaª ustawiony poprawnie to program powinien zatrzyma si w odpowiednim miejscu. Wypiszmy teraz warto± a i b p r i n t a p r i n t b Lub lepiej: p r i n t a b Widzimy zatem,»e instrukcja wakowa if nie ma mo»liwo±ci zadziaªa, mimo,»e zmienne a i b bez w tpienia mo»na uzna za prawie równe 1. Standardowym sposobem na rozwi znie tego problemu jest obliczanie ró»nicy pomi dzy zmiennymi a b i nast pnie sprawdzenie czy ró»nica ta jest mniejsza od jakiej± zadanej wielko±ci eps. Dobrym zwyczajem jest ograniczanie wszystkich niesko«czonych p tli do sko«czonej z góry zadanej maksymalnej liczby iteracji. Prosz zobaczy jak problem2 zostaª rozwi zany w funkcji problem2_ok. 3 Inne problemy pojawiaj ce si na laboratoriach Nie ma nic gorszego ni» stracony czas na szukanie gªupich bª dów... Poni»sze uwagi maj na zadanie skróci ten czas. 4

3.1 Zerowanie tablic Samodzielna alokacja tablicy za pomoc operatora new, czy malloc nie gwarantuje,»e dane w utworzonych tablicach b d wyzerowane. Dlatego dobrym nawykiem jest zerowanie tablic zaraz po ich utworzeniu. Do tego celu mo»na wykorzysta samodzielnie napisane p tle po elementach tablicy, funkcje memset, czy w przypadku operatora new mo»na skorzysta z konstrukcji double data = new double [ 1 0 0 ] ( ) ; Dodanie () spowoduje,»e utworzona tablica b dzie wyzerowana. Wi cej sposobów na rozwi zanie tego problemu mo»na znale¹ np: http://stackoverflow.com/questions/2204176/how-to-initialise-memory-with-new-operator-in-c 3.2 Warto± bezwzgl dna - problem fabs() i abs(). Bardzo cz sto w pisanych na tych laboratoriach programach zajdzie potrzeba policzenia warto±ci bezwzgl dnej z jakiej± wielko±ci. Do tego celu b dziemy wykorzystywa funkcje abs lub fabs w zale»no±ci od j zyka. W standardzie C funkcja abs jako argument przyjmuje liczby caªkowite wobec tego abs(0.01) zostanie potraktowane jako abs(0), gdy» 0.01 zostanie obci te do warto±ci caªkowitej 0. Zatem waek abs(0.01) < 0.0001 zostanie speªniony, co jest nie prawd. W programach pisanych w j zyku C trzeba b dzie korzysta z dedykowanej liczbom zmiennoprzecinkowym funkcji fabs. Zatem poprawne b dzie napisanie fabs(0.01) < 0.0001. W j zyku C++ problem ten nie wyst puje i funkcja abs zadziaªa poprawnie. Dlatego te» osoby przyzwyczajone do C++ i pisz ce programy w C bardzo cz sto popeªniaj ten bª d. Bezpieczniej jest jednak pisa std::abs. 3.3 Zbyt rzadkie sprawdzanie kodu. Dobrym zwyczajem jest cz ste sprawdzanie poprawno±ci dziaªania kodu. Programy s krótkie a sama kompilacja trwa uªamek sekundy, zatem warto po ka»dej dokonanej modykacji kodu sprawdzi program, czy wykonuje si poprawnie nawet je»eli nie speªnia jeszcze wymaganej funkcjonalno±ci. Pozwoli to na szybkie wykrycie takich problemów jak brak inicjalizacji zmiennych, naruszenie pami ci itp. 3.4 Wypisywanie kontrolnych warto±ci. Kolejnym dobrym zwyczajem jest wypisywanie dla kontroli warto±ci ró»nych zmiennych u»ywanych przez program, w kolejnych etapach dziaªania programu. Wypisywanie to mo»e odbywa si np. do pliku w przypadku tablic, czy do konsoli. Takie problemy jak warto±ci NaN, NULL czy podobne mo»na bardzo szybko w ten sposób zlokalizowa. 3.5 Moduªowo± programów. W trakcie pisania programów bardzo cz sto zajdzie potrzeba rozwi zywania tego samo problemu ale z wykorzystaniem innej procedury numerycznej. Pisz c kilka razy ten sam kod, bardzo proste zadanie mo»e przerodzi si w kod o dªugo±ci si gaj cy nawet tysi ca linii kodu. Szukanie bªedu w takim kodzie staje si o wiele bardziej trudniejsze. Okazuje si,»e korzystaj c z takich udogodnie«jak funkcje pomocnicze, wska¹niki na funkcje, czy szablony mo»na ten sam kod skróci w elegancki sposób nawet do 100-200 linijek. Dla przykªadu: mamy do rozwi zania równanie ró»niczkowe dy dx = ecos(10x) sin(3x) π ( x 2 1 ), dobrym zwyczajem jest zastosowanie funkcji pomocniczej 5

double f ( double &x ) ( return exp ( cos (10 x ) ) s i n (3 x) M_PI ( x x 1)); zamiast pisania explicite prawej strony powy»szego równania ró»niczkowego w ka»dym miejscu programu. Je»eli tre± zadania ulegnie zmianie albo pomylimy si w denicji funkcji f (np. podczas przepisywania z tre±ci zadania) wtedy wystarczy poprawi tylko jedn linijk w funkcji f, w przeciwnym wypadku tych zmian mo»e by bardzo du»o, co mo»e prowadzi do pomyªek i straconego czasu. 3.6 Efekt Copy-Paste'a Bardzo cz sto zdarza si skorzystanie z analogicznego fragmentu kodu w ró»nych miejscach programu. Zwyczajem jest kopiowanie tego kodu (w celu zaoszcz dzenia czasu), a nast pnie jego modykacja tak, aby dziaªaª pod konkretne zadanie. W przypadku kopiowania du»ych fragmentów kodu, problemem jest nie poprawienie wszystkich zmian jakie trzeba dokona, aby kod dziaªaª poprawnie. Niestety tego typu bª dy s zwykle nie wykrywalne przez kompilator, czy debugger, a szukanie ich jest bardzo uci»liwe. Poni»ej znajduje si przykªad ilustruj cy problem: zaªó»my,»e w pierwszej cz ±ci zadania mamy do wykonania p tle: a = 0 ; f o r ( i n t i = 0 ; i < 100 ; i++) a = func_a ( a, i ) ; a w drugiej cz ±ci zadanie jest analogiczne, ale zamiast func_a mamy u»y inn funkcj np. func_b. Standardowo kopiujemy kod i zmieniamy wsz dzie z a na b, ale przypadkiem zapominamy zmieni jednej rzeczy: b = 0 ; f o r ( i n t i = 0 ; i < 100 ; i++) a = func_a (b, i ) ; W takim przypadku, program zadziaªa poprawnie, a warto± a i b na ko«cu programu b d zªe. Powy»szy problem jest bardzo oczywisty, ale nale»y pami ta,»e w rzeczywistych programach pisanych na laboratoriach zajdzie potrzeba skopiowania nawet kilkudziesi ciu linijek kodu, a miejsc do popeªnienia bª du b dzie znacznie wi cej. Cz ±ciowym sposobem na rozwi zanie tego problemu jest kopiowanie kodu porcjami, w takich ilo±ciach, aby w ka»dej porcji liczba zmian do wprowadzenia nie byªa zbyt du»a. 6