Strona główna » C++ » Kurs » Debugowanie programu
 

Debugowanie programu

Wstęp

Podczas pisania aplikacji błędy są nieuniknione. Każda nawet najdrobniejsza literówka może spowodować, że program przestanie działać prawidłowo. W przypadku pisania kodu proces debugowania może zbiegać się do dokładnego przeanalizowania kodu, wypisywania wartości co jakiś czas lub użycia debuggera. Ostatnie wymienione rozwiązanie wymaga kilku godzin dodatkowej nauki, ale jest zdecydowanie najlepszą metodą. W niniejszym artykule postaram się przedstawić jak szybko i jak najdokładniej naprawić kod.

Debugowanie dotyczy zarówno usuwania błędów kompilacji jak również błędów działania programu. W tym pierwszym przypadku dobry kompilator potrafi dostarczyć wielu, bardzo użytecznych informacji: czy chodzi o zgubiony średnik, czy podana funkcja nie istnieje, albo nie przyjmuje takich argumentów. Problemy jednak zaczynają się kiedy błąd dotyczy działania programu. Komputer ślepo podąża za wpisanymi instrukcjami i nie jest w stanie sam sprawdzić czy działa tak jak powinien. W tym momencie do działania wkracza czynnik ludzki.

Poprawność działania

Znalezienie błędu

Pierwszym krokiem do usunięcia błędu jest.. znalezienie błędu. Brzmi to dość oczywiście, ale część błędów występuje tylko w określonym środowisku. Przykładowo skrypt strony internetowej nie działa tylko w jednej konkretnej przeglądarce. Zebranie konkretnych informacji w tym przypadku np. co to za przeglądarka, system, specyfikacja programu pozwala określić w którym momencie błąd występuje. Załóżmy, że skrypt nie potrafi odczytać jakieś właściwości obiektu - bardzo możliwe, że w tej przeglądarce nazywa się ona inaczej.

Wykonanie testów

Po wykryciu błędu i po jego najdokładniejszym opisaniu tester oprogramowania, ale częściej nawet sam programista stara się odtworzyć środowisko w którym dany błąd wystąpił. Ma to najczęściej na celu dokładniejszego zbadania zgłoszenia np. poprzez analizę pamięci lub użycia wersji testowej, która dostarcza więcej informacji o działaniu aplikacji niż wersja dostarczona dla użytkownika. Bardzo często okazuje się, że problem nie dotyczy samego programu, a innego zainstalowanego oprogramowania środowiska. Jeśli rzeczywiście nie jest to wina kodu to zwykle nie wydaje się nowej wersji programu, a jedynie zalecenia dotyczące środowiska np. potrzebę uaktualnienia zewnętrznych bibliotek.

Izolacja błędu

Jeśli jednak problem dotyczy kodu to należy dokładnie określić, która linijka może to powodować. Zazwyczaj jest to możliwe poprzez rejestr zdarzeń. Program w trakcie wykonywania zgłasza, która funkcja jest aktualnie wykonywana. Tego typu zabieg pozwala wyodrębnić problematyczną funkcję. Istnieje możliwość oczywiście, aby takie rejestrowanie zgłaszała każda linijka kodu. Jest to sposób, ale bardzo mało praktyczny - kod staje się mało czytelny, ponieważ co druga linijka zgłasza co robi program. Co więcej takie ciągłe zgłoszenia mogą doprowadzić do zaalokowania bardzo dużej ilości pamięci systemowej lub na dysku.

Rejestr zdarzeń można prowadzić na różne sposoby. Jeden z nich będzie dopisywał kolejne zgłoszenia do określonego pliku na dysku. Innym pomysłem bardziej wygodnym dla małych programów jest wypisania błędów bezpośrednio na ekran konsoli. Należy jednak pamiętać, że każde zgłoszenie do rejestru to dodatkowa linijka kodu, a co za tym idzie wiążę się to z dodatkowym nakładem pracy.

W przypadku małych programów jednak można z tego skorzystać poprzez dzielenie programu na sekcję. Przykładowo program ma wczytać od użytkownika liczby, następnie je odpowiednio zmodyfikować, a następnie je wypisać. Wtedy program do rejestru mógłby zgłaszać "pobieranie danych", modyfikacja danych i na koniec wypisywanie danych. Jednak zdecydowanie lepszym pomysłem jest poznanie debuggera, który obecnie występuje chyba w każdym zintegrowanym środowisku programistycznym (IDE).

Debugger

Większość środowisk oferuje zintegrowany debugger. Jest to narzędzie, które dodaje do programu wspomniany wcześniej rejestr zdarzeń. Najczęściej przy jego pomocy można zatrzymać wykonywanie programu, a następnie prześledzić ścieżkę jak program zawędrował do tego miejsca tj. jakie funkcje były po kolei wywoływane i z której do której linijki następowało przejście, możliwość sprawdzenia dowolnej wartości zmiennej, a nawet ręcznego wywołania funkcji z dowolnym argumentem.

Program można wstrzymać na dwa sposoby: poprzez wciśnięcie przycisku pauza w IDE, albo poprzez ustawienie Punktu zatrzymania (ang. Breakpoint). Program po osiągnięciu linijki, gdzie taki punkt się znajduje wstrzymuje wykonywanie programu i udostępnia użytkownika wspomniane w poprzednim akapicie narzędzia. Nie należy się martwić, że do wykrycia problemu należy zapunktować całą funkcję. Dobry, przydatny debugger po wykryciu błędu od razu wskaże w której linijce i określi czego dany problem dotyczy. Z kolei bardzo dobry debugger pozwoli jeszcze zmodyfikować program i wznowić jego wykonywanie jak gdyby program tak od początku był napisany. Warto pamiętać, aby potem wywołać program jeszcze raz, bo może wystąpić problem z danymi, które były zmodyfikowane przez oryginalną wersję funkcji.

Wdrażanie rozwiązania

Ostatnim krokiem debugowania jest wydanie nowej wersji programu i jej opublikowanie, albo napisanie zaleceń. Zalecenia mogą dotyczyć poprawności danych wejściowych. Często występującym problemem jest stosowanie przez użytkowników specyficznych znaków, które dla programu znaczą całkowicie inne rzeczy. Jednak najważniejsze jest to, aby przed wydaniem nowej wersji upewnić się, że program działa z przykładowymi danymi i rozwiązywany problem już nie pojawia się.

Testowanie jest szczególnie ważne kiedy każdy członek zespołu odpowiada za inny komponent programu. Bardzo często rozwiązanie jednego problemu np. zmiana zwracanego wyniku i istniejąca potrzeba dostosowania innej funkcji do tej zmiany może lawinowo spowodować powstanie kolejnych błędów poprzez naprawianie jednego wykrytego. W zależności od stopnia błędu niektórych błędów nigdy firma nie naprawia, ponieważ dostarczenie ich wszędzie mogłoby być niemożliwe i mogłoby powodować błędy kompatybilności.