
Visual Studio ? jak sprawnie debugować?
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.
Szukasz informacji o Visual Studio? Kliknij poniżej:
Zobacz nasze propozycje
-
(53.40 zł najniższa cena z 30 dni)
56,07 zł89,00 zł -
(23.94 zł najniższa cena z 30 dni)
25,54 zł39,90 zł -
(ebook)
(29.40 zł najniższa cena z 30 dni)
31,36 zł49,00 zł -
(41.40 zł najniższa cena z 30 dni)
44,16 zł69,00 zł -
(ebook)
(11.99 zł najniższa cena z 30 dni)
11,99 zł39,90 zł -
(59.40 zł najniższa cena z 30 dni)
59,40 zł99,00 zł -
(53.40 zł najniższa cena z 30 dni)
56,96 zł89,00 zł -
(47.40 zł najniższa cena z 30 dni)
48,19 zł79,00 zł -
(ebook)
(41.40 zł najniższa cena z 30 dni)
44,16 zł69,00 zł -
(77.40 zł najniższa cena z 30 dni)
82,56 zł129,00 zł -
(35.40 zł najniższa cena z 30 dni)
37,76 zł59,00 zł -
(35.40 zł najniższa cena z 30 dni)
36,58 zł59,00 zł -
(23.94 zł najniższa cena z 30 dni)
25,14 zł39,90 zł -
(41.40 zł najniższa cena z 30 dni)
44,16 zł69,00 zł -
(35.40 zł najniższa cena z 30 dni)
37,76 zł59,00 zł -
(59.40 zł najniższa cena z 30 dni)
63,36 zł99,00 zł -
(53.40 zł najniższa cena z 30 dni)
55,18 zł89,00 zł -
(53.40 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(53.40 zł najniższa cena z 30 dni)
56,07 zł89,00 zł -
(22.20 zł najniższa cena z 30 dni)
23,68 zł37,00 zł