Sdílet prostřednictvím


Ladění pro absolutní začátečníky

Bez selhání kód, který píšeme jako vývojáři softwaru, nedělá vždy to, co jsme očekávali. Někdy to dělá něco úplně jiného! Když dojde k neočekávanému problému, dalším úkolem je zjistit, proč a i když bychom mohli být lákaví jen sledovat náš kód po dobu hodin, je jednodušší a efektivnější používat ladicí nástroj nebo ladicí program.

Ladicí program bohužel není něco, co může magicky odhalit všechny problémy nebo chyby v našem kódu. ladění znamená spuštění kódu krok za krokem v nástroji pro ladění, jako je Visual Studio, abyste našli přesný bod, kdy jste způsobili programátorskou chybu. Pak pochopíte, jaké opravy potřebujete udělat v kódu a nástrojích pro ladění, často vám umožní provádět dočasné změny, abyste mohli program dál spouštět.

Efektivní použití ladicího programu je také dovednost, která potřebuje čas a praxi se učit, ale v konečném důsledku je základním úkolem každého vývojáře softwaru. V tomto článku představíme základní principy ladění a nabídneme tipy, které vám pomůžou začít.

Objasnění problému tím, že se ptáte na správné otázky

Pomůže vám to objasnit problém, na který jste narazili, než se ho pokusíte opravit. Očekáváme, že jste už narazili na problém ve vašem kódu, jinak byste se tady nepokoušeli zjistit, jak ho ladit. Než tedy začnete s laděním, ujistěte se, že jste identifikovali problém, který se pokoušíte vyřešit:

  • Co jste očekávali, že váš kód udělá?

  • Co se místo toho stalo?

    Pokud při spuštění aplikace narazíte na chybu (výjimku), může to být dobrá věc! Výjimkou je neočekávaná událost, ke které došlo při spuštění kódu, obvykle k nějaké chybě. Nástroj pro ladění vás může dostat na přesné místo v kódu, kde došlo k výjimce, a může vám pomoct prozkoumat možné opravy.

    Pokud se stalo něco jiného, jaký je příznak problému? Už máte podezření, kde k tomuto problému došlo ve vašem kódu? Pokud například váš kód zobrazí nějaký text, ale text je nesprávný, víte, že data jsou chybná nebo kód, který nastavil zobrazovaný text, má nějaký druh chyby. Krokováním kódu v ladicím programu můžete prozkoumat každou a každou změnu proměnných a zjistit, kdy a jak jsou přiřazeny nesprávné hodnoty.

Prozkoumání předpokladů

Než prošetříte chybu nebo omyl, zamyslete se nad předpoklady, které vás vedly k očekávání určitého výsledku. Skryté nebo neznámé předpoklady můžou překážet v identifikaci problému, i když se přímo díváte na jeho příčinu v ladicím programu. Možná máte dlouhý seznam možných předpokladů! Tady je několik otázek, na které se můžete zeptat, abyste mohli zpochybnit své předpoklady.

  • Používáte správné rozhraní API (to znamená správný objekt, funkci, metodu nebo vlastnost)? Rozhraní API, které používáte, nemusí dělat to, co si myslíte. (Po prozkoumání volání rozhraní API v ladicím programu může oprava vyžadovat cestu do dokumentace, která vám pomůže identifikovat správné rozhraní API.)

  • Používáte rozhraní API správně? Možná jste použili správné rozhraní API, ale nepoužívali ho správným způsobem.

  • Obsahuje váš kód nějaké překlepy? Některé překlepy, například jednoduché chybně napsané názvy proměnných, můžou být obtížně vidět, zejména při práci s jazyky, které nevyžadují deklarování proměnných před použitím.

  • Provedli jste v kódu změnu a předpokládáte, že nesouvisí s problémem, který vidíte?

  • Očekávali jste, že objekt nebo proměnná obsahují určitou hodnotu (nebo určitý typ hodnoty), která se liší od toho, co se skutečně stalo?

  • Znáte záměr kódu? Ladění kódu někoho jiného je často obtížnější. Pokud se nejedná o váš kód, je možné, že budete muset věnovat čas tomu, co kód dělá, abyste ho mohli efektivně ladit.

    Spropitné

    Při psaní kódu začněte malými a začněte kódem, který funguje! (Tady je užitečný dobrý vzorový kód.) Někdy je jednodušší opravit velkou nebo složitou sadu kódu tím, že začnete s malou částí kódu, která ukazuje základní úlohu, kterou se pokoušíte dosáhnout. Pak můžete upravit nebo přidat kód přírůstkově a v každém okamžiku testovat chyby.

Dotazováním předpokladů můžete zkrátit dobu potřebnou k nalezení problému v kódu. Můžete také zkrátit dobu potřebnou k vyřešení problému.

Projděte si kód v režimu ladění a zjistěte, kde k problému došlo.

Při normálním spuštění aplikace se zobrazí chyby a nesprávné výsledky až po spuštění kódu. Program se také může neočekávaně ukončit, aniž byste řekli, proč.

Když spustíte aplikaci v ladicím režimu, který se označuje také jako režim ladění, ladicí program aktivně monitoruje vše, co se děje při spuštění programu. Umožňuje také pozastavit aplikaci v libovolném okamžiku, abyste prozkoumali její stav, a pak krokujte řádkem kódu po řádku a sledujte všechny podrobnosti, jak se to stane.

V sadě Visual Studio přejdete do režimu ladění pomocí F5 (nebo zvolením příkazu z nabídky Ladění>Spustit ladění nebo stisknutím tlačítka Spustit laděníIkona zobrazující tlačítko Spustit ladění. na panelu nástrojů Ladění). Pokud dojde k nějaké výjimce, Pomocník pro výjimky ve Visual Studio vás zavede na přesné místo, kde výjimka nastala, a poskytne další užitečné informace. Další informace o zpracování výjimek v kódu naleznete v tématu Techniky ladění a nástroje.

Pokud jste nedostali výjimku, pravděpodobně máte dobrou představu o tom, kde hledat problém v kódu. V tomto kroku použijete zarážky s ladicím programem, abyste se mohli důkladněji podívat na kód. Body zlomu jsou nejdůležitější a základní funkcí spolehlivého ladění. Zarážka označuje, kde má Visual Studio pozastavit spuštěný kód, abyste se mohli podívat na hodnoty proměnných nebo na chování paměti, pořadí, ve kterém se kód spouští.

Ve Visual Studio můžete rychle nastavit zarážku kliknutím na levý okraj vedle řádku kódu. Nebo umístěte kurzor na čáru a stiskněte F9.

Abychom vám pomohli tyto koncepty ilustrovat, projdeme si ukázkový kód, který už obsahuje několik chyb. Používáme jazyk C#, ale funkce ladění platí pro Visual Basic, C++, JavaScript, Python a další podporované jazyky. K dispozici je také ukázkový kód pro Visual Basic, ale snímky obrazovky jsou v jazyce C#.

Vytvoření ukázkové aplikace (s některými chybami)

Dále vytvoříte aplikaci, která obsahuje několik chyb.

  1. Musíte mít nainstalovanou sadu Visual Studio a nainstalovanou úlohu vývoj desktopových aplikací .NET.

    Pokud jste ještě nenainstalovali Visual Studio, přejděte na stránku s možnostmi stažení Visual Studio a nainstalujte ji zdarma.

    Pokud potřebujete nainstalovat pracovní zátěž, ale Visual Studio již máte, vyberte Tools>Získat nástroje a funkce. Spustí se instalační program sady Visual Studio. Zvolte úlohu vývoje desktopových aplikací .NET a pak zvolte Upravit.

  2. Otevřete Visual Studio.

    V úvodním okně zvolte Vytvořit nový projekt. Do vyhledávacího pole zadejte konzoly , vyberte jazyka C# nebo jazyka Visual Basic a pak zvolte konzolové aplikace pro .NET. Zvolte Další. Jako název projektu zadejte ConsoleApp_FirstApp a vyberte Další.

    Pokud použijete jiný název projektu, budete muset upravit hodnotu oboru názvů tak, aby odpovídala názvu projektu při kopírování ukázkového kódu.

    Zvolte buď doporučenou cílovou architekturu, nebo .NET 8, a pak zvolte Vytvořit.

    Pokud šablonu projektu konzolové aplikace pro .NET nevidíte, přejděte na Tools>Get Tools and Features, která otevře instalační program sady Visual Studio. Zvolte úlohu vývoje desktopových aplikací .NET a pak zvolte Upravit.

    Visual Studio vytvoří projekt konzoly, který se zobrazí v průzkumníku řešení v pravém podokně.

  3. V Program.cs (nebo Program.vb) nahraďte veškerý výchozí kód následujícím kódem. (Nejprve vyberte správnou kartu jazyka, jazyk C# nebo Visual Basic.)

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApp_FirstApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Welcome to Galaxy News!");
                IterateThroughList();
                Console.ReadKey();
            }
    
            private static void IterateThroughList()
            {
                var theGalaxies = new List<Galaxy>
            {
                new Galaxy() { Name="Tadpole", MegaLightYears=400, GalaxyType=new GType('S')},
                new Galaxy() { Name="Pinwheel", MegaLightYears=25, GalaxyType=new GType('S')},
                new Galaxy() { Name="Cartwheel", MegaLightYears=500, GalaxyType=new GType('L')},
                new Galaxy() { Name="Small Magellanic Cloud", MegaLightYears=.2, GalaxyType=new GType('I')},
                new Galaxy() { Name="Andromeda", MegaLightYears=3, GalaxyType=new GType('S')},
                new Galaxy() { Name="Maffei 1", MegaLightYears=11, GalaxyType=new GType('E')}
            };
    
                foreach (Galaxy theGalaxy in theGalaxies)
                {
                    Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears + ",  " + theGalaxy.GalaxyType);
                }
    
                // Expected Output:
                //  Tadpole  400,  Spiral
                //  Pinwheel  25,  Spiral
                //  Cartwheel, 500,  Lenticular
                //  Small Magellanic Cloud .2,  Irregular
                //  Andromeda  3,  Spiral
                //  Maffei 1,  11,  Elliptical
            }
        }
    
        public class Galaxy
        {
            public string Name { get; set; }
    
            public double MegaLightYears { get; set; }
            public object GalaxyType { get; set; }
    
        }
    
        public class GType
        {
            public GType(char type)
            {
                switch(type)
                {
                    case 'S':
                        MyGType = Type.Spiral;
                        break;
                    case 'E':
                        MyGType = Type.Elliptical;
                        break;
                    case 'l':
                        MyGType = Type.Irregular;
                        break;
                    case 'L':
                        MyGType = Type.Lenticular;
                        break;
                    default:
                        break;
                }
            }
            public object MyGType { get; set; }
            private enum Type { Spiral, Elliptical, Irregular, Lenticular}
        }
    }
    

    Naším záměrem tohoto kódu je zobrazit název galaxie, vzdálenost k galaxii a typ galaxie všechny v seznamu. Pro ladění je důležité pochopit záměr kódu. Tady je formát jednoho řádku ze seznamu, který chceme zobrazit ve výstupu:

    galaxy name, vzdálenost, typ galaxie.

Spuštění aplikace

Stiskněte klávesu F5 nebo tlačítko Spustit laděníikona zobrazující tlačítko Spustit ladění. na panelu nástrojů ladění umístěném nad editorem kódu.

Aplikace se spustí a žádné výjimky nejsou ladicím programem zobrazeny. Výstup, který se zobrazí v okně konzoly, ale není to, co očekáváte. Tady je očekávaný výstup:

Tadpole  400,  Spiral
Pinwheel  25,  Spiral
Cartwheel, 500,  Lenticular
Small Magellanic Cloud .2,  Irregular
Andromeda  3,  Spiral
Maffei 1,  Elliptical

Ale místo toho se zobrazí tento výstup:

Tadpole  400,  ConsoleApp_FirstApp.GType
Pinwheel  25,  ConsoleApp_FirstApp.GType
Cartwheel, 500,  ConsoleApp_FirstApp.GType
Small Magellanic Cloud .2,  ConsoleApp_FirstApp.GType
Andromeda  3,  ConsoleApp_FirstApp.GType
Maffei 1, 11,  ConsoleApp_FirstApp.GType

Když se podíváme na výstup a náš kód, víme, že GType je název třídy, která ukládá typ galaxie. Snažíme se ukázat skutečný typ galaxie (například "Spirála"), ne název třídy!

Ladění aplikace

  1. Když je aplikace stále spuštěná, vložte zarážku.

    Ve smyčce foreach klikněte pravým tlačítkem myši vedle metody Console.WriteLine pro zobrazení místní nabídky a z fly-out nabídky vyberte Zarážku>Vložit zarážku.

    foreach (Galaxy theGalaxy in theGalaxies)
    {
        Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears + ",  " + theGalaxy.GalaxyType);
    }
    

    Když nastavíte zarážku, zobrazí se na levém okraji červená tečka.

    Když vidíte problém ve výstupu, začnete ladit tím, že se podíváte na předcházející kód, který určuje výstup v ladicím programu.

  2. Vyberte ikonu RestartApp, která zobrazuje tlačítko RestartApp na panelu nástrojů Ladění. Poté vyberte tlačítko na panelu nástrojů Ladění (kombinace klávesCtrl + Shift + F5).

    Aplikace se pozastaví na bodu přerušení, který jste nastavili. Žluté zvýraznění označuje, kde je ladicí program pozastavený (žlutý řádek kódu ještě nebyl proveden).

  3. Přejeďte myší nad proměnnou GalaxyType napravo, a poté nalevo od ikony klíče rozbalte theGalaxy.GalaxyType. Vidíte, že GalaxyType obsahuje vlastnost MyGTypea hodnota vlastnosti je nastavena na Spiral.

    Snímek obrazovky ladicího programu Visual Studio se žlutým řádkem kódu a nabídkou otevřenou pod vlastností Galaxy GalaxyType.

    "Spirála" je ve skutečnosti správná hodnota, kterou jste očekávali tisknout do konzoly! Je to dobrý začátek, že máte přístup k hodnotě v tomto kódu během spuštění aplikace. V tomto scénáři používáme nesprávné rozhraní API. Pojďme se podívat, jestli to můžete opravit při spouštění kódu v ladicím programu.

  4. Ve stejném kódu, zatímco stále ladíte, umístěte kurzor na konec theGalaxy.GalaxyType a změňte ho na theGalaxy.GalaxyType.MyGType. I když můžete provést úpravy, editor kódu zobrazí chybu (červená vlnovka). (V jazyce Visual Basic se chyba nezobrazuje a tato část kódu funguje.)

  5. Stisknutím klávesy F11 (Ladit>Krok do nebo tlačítko Krok do na panelu nástrojů Ladění) spusťte aktuální řádek kódu.

    F11 posune ladicí program kupředu (a spustí kód) po jednom příkazu. F10 (Krok nad) je podobný příkaz a oba jsou užitečné při učení, jak používat ladicí program.

    Když se pokusíte posunout ladicí program, zobrazí se dialogové okno Hot Reload, které oznamuje, že úpravy nelze zkompilovat.

    Snímek obrazovky ladicího programu sady Visual Studio se zvýrazněným řádkem kódu červeně a polem se zprávou s vybranou možností Upravit

    Zobrazí se dialogové okno Upravit a pokračovat, které indikuje, že úpravy nelze zkompilovat.

    Snímek obrazovky ladicího programu sady Visual Studio se zvýrazněným řádkem kódu červeně a polem se zprávou s vybranou možností Upravit

    Poznámka

    Pro ladění ukázkového kódu jazyka Visual Basic přeskočte několik dalších kroků, dokud nebudete vyzváni, abyste klikli na RestartovatIkona restartování aplikace na panelu nástrojů ladění..

  6. Vyberte Upravit v dialogovém okně Přehrání za běhu nebo Upravit a pokračovat. Nyní vidíte chybovou zprávu v okně seznamu chyb . Tato chyba značí, že 'object' neobsahuje definici MyGType.

    snímek obrazovky ladicího programu sady Visual Studio se zvýrazněným řádkem kódu červeně a oknem Seznam chyb se dvěma uvedenými chybami.

    I když nastavíme každou galaxii s objektem typu GType (který má vlastnost MyGType), ladicí program nerozpozná theGalaxy objekt jako objekt typu GType. Co se děje? Chcete se podívat na jakýkoli kód, který nastaví typ galaxie. Když to uděláte, vidíte, že třída GType rozhodně má vlastnost MyGType, ale něco není v pořádku. Chybová zpráva o object se ukáže jako vodítko; pro interpret jazyka se typ jeví jako objekt typu object místo objektu typu GType.

  7. Při pohledu na kód související s nastavením typu galaxie zjistíte, že vlastnost GalaxyType třídy Galaxy je určena jako object místo GType.

    public object GalaxyType { get; set; }
    
  8. Změňte předchozí kód následujícím způsobem:

    public GType GalaxyType { get; set; }
    
  9. Vyberte ikonu Restartovat, která zobrazuje tlačítko Restartovat aplikaci na panelu nástrojů Ladění. Pomocí tlačítka na panelu nástrojů Ladění (Ctrl + Shift + F5) proveďte opětovné kompilování kódu a restartování.

    Nyní, když se ladicí program pozastaví na Console.WriteLine, můžete najet myší na theGalaxy.GalaxyType.MyGTypea zjistit, že hodnota je správně nastavená.

  10. Odeberte zarážku kliknutím na kruh zarážky na levém okraji (nebo klikněte pravým tlačítkem myši a zvolte Zarážku>Odstranit zarážku) a potom pokračujte stisknutím klávesy F5.

    Aplikace se spustí a zobrazí výstup. Vypadá to dobře, ale všimnete si jedné věci. Očekávali jste, že malá magellanicová cloudová galaxie se ve výstupu konzoly zobrazí jako nepravidelná galaxie, ale vůbec nezobrazuje žádný typ galaxie.

    Tadpole  400,  Spiral
    Pinwheel  25,  Spiral
    Cartwheel, 500,  Lenticular
    Small Magellanic Cloud .2,
    Andromeda  3,  Spiral
    Maffei 1,  Elliptical
    
  11. Nastavte zarážku na tomto řádku kódu před příkazem switch (před příkazem Select v jazyce Visual Basic).

    public GType(char type)
    

    Tento kód je tam, kde je typ galaxie nastaven, takže se na něj chceme podívat podrobněji.

  12. Vyberte ikonu Restartovatznázorňující tlačítko Restartovat aplikaci na Panelu nástrojů ladění. Stiskněte tlačítko na Panelu nástrojů ladění (Ctrl + Shift + F5) pro restartování.

    Ladicí program se pozastaví na řádku kódu, kde nastavíte bod přerušení.

  13. Umístěte kurzor myši nad proměnnou type. Zobrazí se hodnota S (za kódem znaku). Máte zájem o hodnotu I, jak víte, je to typ nepravidelné galaxie.

  14. Stiskněte F5 a najeďte myší na proměnnou type znovu. Tento krok opakujte, dokud neuvidíte hodnotu I v proměnné type.

    snímek obrazovky ladicího programu sady Visual Studio se žlutým řádkem kódu a oknem s hodnotou proměnné typu 73 I.

  15. Nyní stiskněte F11 (Ladění>krok do).

  16. Stiskněte F11, dokud se nezastavíte na řádku kódu v příkazu switch pro hodnotu "I" (Select příkaz pro Visual Basic). Tady vidíte jasný problém vyplývající z překlepu. Očekávali jste, že kód přejde na místo, kde nastaví MyGType jako nepravidelný typ galaxie, ale ladicí program tento kód úplně přeskočí a pozastaví se na default části příkazu switch (Else příkaz v jazyce Visual Basic).

    Snímek obrazovky s chybou překlepu

    Při pohledu na kód se v příkazu case 'l' zobrazí překlep. Mělo by to být case 'I'.

  17. Vyberte kód pro case 'l' a nahraďte ho case 'I'.

  18. Odstraňte zarážku a pak výběrem tlačítka Restartovat restartujte aplikaci.

    Chyby jsou opraveny a uvidíte výstup, který očekáváte.

    Stisknutím libovolné klávesy aplikaci dokončete.

Shrnutí

Když se zobrazí problém, pomocí ladicího programu a krokových příkazů, jako je F10 a F11 najít oblast kódu s problémem.

Poznámka

Pokud je obtížné identifikovat oblast kódu, ve které k problému dochází, nastavte zarážku v kódu, který se spustí před výskytem problému, a pak použijte příkazy kroků, dokud neuvidíte manifest problému. K protokolování zpráv do okna Výstup můžete použít také trasovací body . Když se podíváte na protokolované zprávy (a zjistíte, které zprávy ještě nebyly zaprotokolovány!), můžete často izolovat oblast kódu s problémem. Možná budete muset tento proces několikrát zopakovat, abyste ho zúžili.

Když zjistíte část kódu s problémem, použijte ladicí program k prozkoumání. Pokud chcete zjistit příčinu problému, zkontrolujte kód problému při spuštění aplikace v ladicím programu:

  • Zkontrolujte proměnné a zkontrolujte, jestli obsahují typ hodnot, které mají obsahovat. Pokud zjistíte chybnou hodnotu, zjistěte, kde byla nastavena chybná hodnota (abyste zjistili, kde byla hodnota nastavena, možná budete muset ladicí program restartovat, podívat se na zásobník volánínebo obojí).

  • Zkontrolujte, jestli aplikace spouští očekávaný kód. (Například v ukázkové aplikaci jsme očekávali kód pro příkaz switch nastavit typ galaxie na Nepravidelný, ale aplikace kód přeskočila kvůli překlepu.)

Spropitné

Používáte ladicí program, abyste našli chyby. Nástroj pro ladění může najít chyby pro vás pouze v případě, že zná záměr vašeho kódu. Nástroj může znát záměr vašeho kódu pouze v případě, že tento záměr vyjadřujete vy, vývojář. Psaní jednotkových testů je způsob, jak to udělat.

Další kroky

V tomto článku jste se naučili několik obecných principů ladění. V dalším kroku se můžete dozvědět více o ladicím programu.