Kod źródłowy można pisać nawet w najprostszym notatniku, który nie oferuje żadnych dodatkowych funkcji związanych z edycją czy formatowaniem tekstu (n

Kod źródłowy można pisać nawet w najprostszym notatniku, który nie oferuje żadnych dodatkowych funkcji związanych z edycją czy formatowaniem tekstu (nie mówiąc o formatowaniu kodu). Istnieje pewne prawdopodobieństwo, że tak napisany program da się skompilować. Jednak czy wszystko będzie działać po uruchomieniu? Czy pójdzie to szybko i sprawnie? Czy wyłapiemy wszystkie błędy? Cóż… z tym może być pewien problem.   Duże i rozbudowane IDE (a czasem nawet mniejsze edytory pokroju Sublime Text czy Visual Studio Code) oferują zestaw pewnych funkcji, które w wymierny sposób mogą skrócić i ułatwić kodowanie. Czy wyobrażacie sobie dzisiaj edytor dla developera bez:

  • kolorowania składni,
  • automatycznego formatowania kodu,
  • opcji podkreślania błędów,
  • wbudowanej obsługi kompilatora,
  • czy też wreszcie tytułowego debugera?

  Być może tak. Być może nawet czasem poprawiacie „na szybko” jakąś literówkę w HTML-u na serwerze, w notatniku, ale na dłuższą metę byłoby to bardzo męczące. Działanie większości wyżej wymienionych opcji jest dość oczywiste, ale wydaje mi się, że więcej uwagi można poświęcić tytułowemu debugerowi. W tekście będę używać spolszczonej formy, czyli debugera przez jedno „g” (za http://sjp.pl/debuger).    

Podstawowe debugowanie

Wydaje mi się, że jednym z najczęstszych powodów, dla których sięgamy po debuger w języku C#, jest wyjątek NullReferenceException, który objawia się słynnym komunikatem: Object reference not set to an instance of an object. Tego rodzaju wyjątek potrafi uprzykrzyć życie i może on być szczególnie bolesny w sytuacji, gdy pisaliśmy jakiś kod przez tydzień i nagle, z niewiadomych przyczyn, przestał działać. W takim momencie najlepiej jest oczywiście przejrzeć raz napisany kod, ale jeśli to nasze własne rozwiązanie, w większości przypadków przeoczymy problem, który z reguły znajduje się na wyciągnięcie ręki. Dlatego też bardzo często skłaniamy się ku debugerom, które pomogą nam odnaleźć problem.   Debuger, w zależności od konfiguracji, może posiadać różne skróty klawiszowe; warto się ich nauczyć na pamięć. W moim przypadku są to: F5 — Start debugging — uruchamia debugowanie, a także pozwala przeskoczyć do kolejnego breakpointa już w trakcie debugowania. F9 — Toggle breakpoint — włącza/wyłącza breakpoint na wskazanej linii. F10 — Step over — w sytuacji gdy debuger „stoi”, pozwala na przejście do następnej linii w bieżącym kontekście. F11 — Step into — działa podobnie jak Step over, z tym że możemy wejść również do metod z innych klas wywoływanych w bieżącym kontekście (o ile są częścią aktualnego projektu, ewentualnie gdy mamy pliki symboli).   Podczas debugowania możemy najechać kursorem na dowolny element w bieżącym kontekście, by podejrzeć jego zawartość. Spójrzmy na poniższy kod: [sourcecode language="csharp"] using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List<string> list = CreateList(); list.Add("Jan"); } static List<string> CreateList() { return null; } } } [/sourcecode]   Jest on totalnie bez sensu, z miejsca widać, że dojdzie w tym przypadku do katastrofy, co potwierdza poniższy screen (pamiętajcie, że taki program jest w pełni kompilowalny):   Przejście do kolejnej linii spowoduje wygenerowanie wyjątku. Przy okazji tego screenshota warto zwrócić uwagę na małą ikonkę widoczną na prawo od słowa „null”. Pozwala ona na przypięcie podglądu obiektu w taki sposób, że nie zniknie on z naszego ekranu, gdy przesuniemy kursor.    

Okno Watch

Powyższy sposób na podglądanie obiektów jest w porządku, gdy robimy to raz czy dwa. Jeżeli jednak jesteśmy we wnętrzu bardziej złożonego kodu i chcielibyśmy mieć podgląd na różne obiekty, to możemy skorzystać z okienek Watch, które pozwalają na śledzenie stanu obiektów. Dostęp do nich otrzymujemy po wejściu do menu Debug ->Windows -> Watch (tutaj opcja Watch 1 – 4) lub za pomocą skrótów klawiszowych. Spójrzmy na zmodyfikowany wcześniejszej kod aplikacji: [sourcecode language="csharp"] using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List<string> list = CreateList(); list.Add("Jan"); list.Add("Stefan"); list.Add("Basia"); } static List<string> CreateList() { return new List<string>(); } } } [/sourcecode] Ustawcie teraz breakpoint na linii tworzenia naszego obiektu, a następnie w dowolnym polu Watch wpiszcie nazwę naszego obiektu (list) i zatwierdźcie enterem. W kolejnym kroku możecie przesunąć się o linię lub dwie. Powinniście uzyskać efekt jak na screenie poniżej:     W kolejnej linii okna Watch możemy dopisać inny obiekt. W tym przypadku tak naprawdę dostępną mamy jeszcze tylko tablicę argumentów (args), ale w normalnym kodzie będzie tego znacznie więcej :)    

Debugowanie warunkowe

Czasem zdarza się, że chcemy zdebugować sytuację, która zachodzi w pewnych określonych warunkach, np. w momencie gdy licznik w pętli jest powyżej określonej liczby. Normalnie musielibyśmy ustawić breakpoint we wnętrzu pętli i wciskać Continue tyle razy, aż doszlibyśmy. Na szczęście można to zrobić szybciej.   Poniżej teoretyczny problematyczny kod: [sourcecode language="csharp"] using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { for (int i = 0; i < 500; ++i) { Console.WriteLine(i); // Destrukcyjny kod } } } } [/sourcecode]   Załóżmy teraz, że chcemy zatrzymać się na linii z wypluwaniem tekstu, w sytuacji gdy i == 495. Stawiamy w tym miejscu breakpoint, a następnie klikamy w niego PPM i z menu kontekstowego wybieramy opcję Conditions. Następnie dopisujemy warunek i == 495.   Teraz uruchamiamy aplikację i podglądamy wartość i przy pierwszym postoju:     Wszystko się zgadza :) Zaoszczędziliśmy sporo czasu i dotarliśmy do potencjalnie niebezpiecznego miejsca w kodzie.    

Symbole

Jeśli mamy dostęp do plików PDB zewnętrznego dostawcy (lub naszej biblioteki), to możemy je podpiąć lokalnie z komputera czy też z określonego serwera. Aby to zrobić, należy wejść do menu Tools -> Options, a następnie w polu wyszukiwania odnaleźć opcję Symbols. W tym miejscu możemy dodać lokalizację, w której znajdują się nasze pliki PDB :)   Powyższe sposoby to nie wszystko, ale pozwalają na ogarnięcie naprawdę sporej liczby problemów z naszym kodem.  

Jerzy Piechowiak

Altcontroldelete.pl

 


Szukasz informacji o Visual Studio? Kliknij poniżej: