Grafikus C# – Windows Forms tanfolyam › 13.2 lecke Windows Forms · 13.2 lecke · hibakeresés A logikai hibát nem jelzi semmi: a program lefut, csak rossz az eredmény. A leghatékonyabb módszer az, hogy megállítod a programot egy gyanús ponton, és soronként végignézed, mit csinál. Ezt a Visual Studio hibakeresője (debugger) teszi lehetővé. A Breakpoint, Step Into, Step Over
MessageBox-os „kiíratásos” hibakeresés lassú és zajos: a töréspont (breakpoint) és a lépésenkénti futtatás percek alatt megmutatja, hol tér el a program a te elképzelésedtől. Ebben a leckében megtanulod a debug módot, a töréspontokat, a lépések fajtáit (F10, F11, Shift+F11), a feltételes töréspontot és a Windows Forms eseménykezelők hibakeresésének sajátosságait.
A lecke végére
- debug módban indítod a programot (F5), és megkülönbözteted a Ctrl+F5-től;
- töréspontot teszel (és kapcsolsz ki), és érted, hogy a program a sor végrehajtása előtt áll meg;
- helyesen használod a Step Over (F10), Step Into (F11), Step Out (Shift+F11) és Run to Cursor (Ctrl+F10) parancsot;
- feltételes töréspontot és hitszámlálós töréspontot állítasz be (ciklusokhoz);
- tracepointtal naplózol megállás nélkül;
- Windows Forms eseménykezelőkben is hibát keresel.
Mielőtt elkezded
Ehhez a leckéhez a 13.1 lecke (hibafajták) és az 5. fejezet (események) szükséges. A szükséges eszköz a Visual Studio; az itteni billentyűparancsok az alapértelmezett kiosztásra vonatkoznak.
Debug mód és töréspont
| Parancs | Billentyű | Mit csinál? |
|---|---|---|
| Start Debugging | F5 | Elindítja a programot a hibakeresővel: a töréspontoknál megáll. |
| Start Without Debugging | Ctrl+F5 | Hibakereső nélkül indít: a töréspontok hatástalanok. |
| Toggle Breakpoint | F9 | Töréspont be/ki a kurzor sorában (vagy kattintás a bal margóra). |
| Continue | F5 (megállás közben) | Folytatja a futást a következő töréspontig. |
| Stop Debugging | Shift+F5 | Leállítja a programot. |
| Restart | Ctrl+Shift+F5 | Újraindítja debug módban. |
| Break All | Ctrl+Alt+Break | Megállítja a futó (például lefagyott) programot (11.4 lecke). |
private void btnSzamol_Click(object sender, EventArgs e)
{
int n = int.Parse(txtN.Text);
int osszeg = OsszegEgeszig(n); // ● töréspont ide (F9): a program EZ a sor végrehajtása ELŐTT megáll
lblEredmeny.Text = "Összeg: " + osszeg;
}Jósolj!
Töréspontot teszel a int osszeg = OsszegEgeszig(n); sorra, és a program megáll rajta. Mi az osszeg változó értéke ekkor?
Jóslat ellenőrzése
0 (vagy értelmetlen alapérték): a sor még nem hajtódott végre, a változó csak most fog értéket kapni. A töréspont „a sor előtt” áll meg. Lépj egyet (F10), és az érték megjelenik.
Léptetés: Step Over, Step Into, Step Out
| Parancs | Billentyű | Mit csinál? | Mikor? |
|---|---|---|---|
| Step Over | F10 | Végrehajtja az aktuális sort egyben (a hívott metódust is), és megáll a következő soron. | Ha a hívott metódus jó, nem érdekel belül. |
| Step Into | F11 | Ha a sor metódust hív, belép a metódusba, és ott áll meg az első soron. | Ha a hívott metódust gyanúsítod. |
| Step Out | Shift+F11 | Végrehajtja a metódus hátralévő részét, és a hívóhoz tér vissza. | Ha véletlenül belépett, vagy már megtudtad, amit akartál. |
| Run to Cursor | Ctrl+F10 | Odáig fut, ahol a kurzor áll (mintha ideiglenes töréspont lenne). | Ciklus kihagyására, hosszabb szakasz átugrására. |
private int OsszegEgeszig(int n)
{
int osszeg = 0; // ← F11-gyel ide lépsz be a hívásból
for (int i = 1; i < n; i++) // F10-zel soronként: figyeld, mikor áll meg a ciklus!
{
osszeg += i; // itt látod: i = 1, 2, 3, ..., n-1: az n már NEM kerül bele
}
return osszeg; // logikai hiba: i < n helyett i <= n kell
}int.Parse, List.Add) nem, mert a Just My Code beállítás átugorja őket. Ez jó így: nem akarod a keretrendszer belsejét nézni.Jósolj!
A program a osszeg = Atlagol(lista); soron áll. Az Atlagol metódus hibás. Melyik billentyűt nyomod, ha a metódus belsejét szeretnéd megnézni?
Jóslat ellenőrzése
F11 (Step Into): belép az Atlagol metódusba. Az F10 az egész hívást egyben végrehajtaná, és a következő soron állna meg, a belsejét nem látnád.
Haladó töréspontok: feltétel, számláló, tracepoint
Conditional Expression: i == 500 (csak akkor áll meg, ha igaz)
nev == "Anna"
Hit Count: = 100 / >= 50 / multiple of 10
Actions (tracepoint): Log a message: "i = {i}, osszeg = {osszeg}"
[x] Continue execution (naplóz, de NEM áll meg)i == 500. Egy ezer lépéses ciklusban nem kell 499-szer továbblépned. A kifejezés szintaxisa C#.{változó} behelyettesítéssel). Ez a Console.WriteLine/MessageBox „kiíratásos” hibakeresés kódmódosítás nélkül, és nem kell utólag törölni.Jósolj!
Egy 10 000 elemű ciklus 7342. lépésében romlik el az eredmény. Hogyan jutsz oda a leggyorsabban?
Jóslat ellenőrzése
Feltételes töréspontot teszel a ciklus testére: i == 7342 (vagy hit count: = 7342). A program addig szalad, és pontosan ott áll meg; onnan F10-zel lépegetsz.
Hibakeresés Windows Forms programban
// az eseménykezelő a belépési pont: ide tedd a töréspontot, ha a gombnyomás után romlik el valami
private void btnSzamol_Click(object sender, EventArgs e)
{
// ● a gomb megnyomásakor áll meg ITT
string szoveg = txtN.Text;
int n = int.Parse(szoveg);
Szamol(n);
}
// kiíratás az Output ablakba (Debug → Windows → Output): nem zavarja a felületet
System.Diagnostics.Debug.WriteLine("n = " + n); // csak Debug módban fordul bele
// kényszerített megállás a kódból (csak ha a debugger csatlakozik)
if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Break(); }Designer.cs-be. Ha nem tudod, melyik esemény fut, tégy töréspontot több kezelőbe: az áll meg, amelyik valóban lefut (és kiderül, melyik nem hívódik: például nincs bekötve).Debug.WriteLine az Output ablakba ír, és csak Debug fordításban él: Release-ben eltűnik. Kényelmes folyamatos naplózáshoz (13.7 lecke), tracepoint helyett is jó, ha kódba szánod.Jósolj!
Töréspontot teszel a btnSzamol_Click első sorára, a programot elindítod, de a gombra kattintva nem áll meg. Mi lehet az ok?
Jóslat ellenőrzése
Három gyakori ok: (1) a gomb Click eseménye nincs bekötve ehhez a kezelőhöz (Properties → Events); (2) Ctrl+F5-tel indítottad; (3) a töréspont üres/halvány (nem azonos a futó kód: Rebuild). A töréspont, amely „nem áll meg”, maga is információ: a kód nem fut le.
Mit tegyél ide: a Visual Studio megállított programja: a sárga sor, a piros töréspont, a Locals ablak és a Step gombok az eszköztáron.Javasolt fájlnév: winforms-13-2-debug.webp · Alt szöveg: A Visual Studio debug nézete
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. A töréspont nem működik
Piros pont van, de a program nem áll meg. Ellenőrizd: F5-tel indítottad-e (nem Ctrl+F5), Debug konfiguráció-e, és a sor lefut-e (a kezelő be van-e kötve). Üres pont: Rebuild.Ok és javítás
2. Túl sok F10
Egy 5000 elemű ciklust lépegetsz, és percek telnek el. Használj feltételes töréspontot (Ok és javítás
i == 4999), hit countot, vagy Ctrl+F10 (Run to Cursor) a ciklus utáni sorra.
3. Belépett, ahová nem akartál
Az F11 egy másik, ismeretlen metódusba vitt. Shift+F11 (Step Out) visszavisz a hívóhoz. Máskor F10, ha a hívott metódus nem gyanús.Ok és javítás
4. A töréspont a hibás sor után van
A hibás sor már lefutott, mire megáll a program. Tedd a töréspontot a gyanús rész elé, ahol még minden rendben van, és onnan lépkedj.Ok és javítás
5. Eltűnt a változó értéke
A hibakereső „optimalizálva” üzenetet ad a változóra. Release konfigurációban dolgozol. Válts Debug konfigurációra, és építsd újra.Ok és javítás
6. A felület lefagyott a megálláskor
A program ablaka nem reagál, miközben a töréspontnál állsz. Ez normális: a program meg van állítva. F5 folytatja, Shift+F5 leállítja.Ok és javítás
Mini projekt: nyomozó-labor
Kapsz négy metódust, mindegyikben egy logikai hiba van (a program lefut, de rossz az eredmény). Töréspont és léptetés segítségével találd meg és javítsd a hibákat:
- Új projekt: Windows Forms (
Nyomozo), aForm1legyentxtBemenet, négy gomb (btnOsszeg,btnJegy,btnLegnagyobb,btnAtlag) éslblEredmeny. - Másold be a hibás metódusokat (lent), és kösd be a gombokat: a
btnOsszegazOsszegEgeszigt hívja (txtBemenetegész szám), abtnJegyaJegy-et (pontszám), abtnLegnagyobbaLegnagyobb-at (számok szóközzel elválasztva), abtnAtlagazAtlag-ot (szintén). - Hipotézis: minden hibához először írd le, mit vársz (például
OsszegEgeszig(5)= 15), és mit ad a program. - Töréspont és léptetés: tegyél töréspontot a hívásra, F11-gyel lépj a metódusba, F10-zel soronként haladj; jegyezd fel, melyik sornál tér el a valóság a várakozásodtól, és mit mutat a változó (a Locals ablakot a 13.3 leckében részletezzük, itt az egérmutatóval olvasd le az értéket).
- Feltételes töréspont: az
OsszegEgeszig(1000)esetén egy feltételes töréspontot (i == 999) használj; aJegyhibájánál töréspont az adottelse ifsorra. - Tracepoint: az
Atlagciklusában (osszeg += x) állíts be tracepointot (x = {x}, osszeg = {osszeg}), és olvasd le az Output ablakból a menetet megállás nélkül. - Javítás és ellenőrzés: javítsd a négy hibát, és ellenőrizd az előre felírt példákkal (táblázat: bemenet, várt, kapott).
- Nyomozónapló: minden hibához: tünet, hol álltam meg, mit láttam, mi az ok, javítás.
A hibás metódusok (próbáld ki előbb önállóan!)
// 1. 1-től n-ig összeadja a számokat
private int OsszegEgeszig(int n)
{
int osszeg = 0;
for (int i = 1; i < n; i++) { osszeg += i; }
return osszeg;
}
// 2. osztályzat pontszámból: 0-49: 1, 50-64: 2, 65-79: 3, 80-89: 4, 90-100: 5
private string Jegy(int pont)
{
if (pont >= 50) { return "2"; }
else if (pont >= 65) { return "3"; }
else if (pont >= 80) { return "4"; }
else if (pont >= 90) { return "5"; }
return "1";
}
// 3. a legnagyobb szám a tömbben
private int Legnagyobb(int[] tomb)
{
int max = 0;
foreach (int x in tomb) { if (x > max) { max = x; } }
return max;
}
// 4. átlag
private double Atlag(List<int> lista)
{
int osszeg = 0;
foreach (int x in lista) { osszeg += x; }
return osszeg / lista.Count;
}Tippek (ha elakadsz): az 1. hiba a ciklus határa; a 2. a feltételek sorrendje (az első feltétel minden 50 fölöttit elkap); a 3. a kezdőérték (csupa negatív számnál); a 4. az egész osztás (és üres lista esetén DivideByZeroException).
A javított metódusok
// 1. a ciklus határa: i <= n
private int OsszegEgeszig(int n)
{
int osszeg = 0;
for (int i = 1; i <= n; i++) { osszeg += i; }
return osszeg;
}
// 2. a legnagyobb küszöbbel kezdjük (vagy fordított sorrend)
private string Jegy(int pont)
{
if (pont >= 90) { return "5"; }
else if (pont >= 80) { return "4"; }
else if (pont >= 65) { return "3"; }
else if (pont >= 50) { return "2"; }
return "1";
}
// 3. a kezdőérték az első elem; üres tömbre kivétel
private int Legnagyobb(int[] tomb)
{
if (tomb == null || tomb.Length == 0) { throw new ArgumentException("A tömb nem lehet üres."); }
int max = tomb[0];
foreach (int x in tomb) { if (x > max) { max = x; } }
return max;
}
// 4. valós osztás, üres lista védelme
private double Atlag(List<int> lista)
{
if (lista.Count == 0) { throw new ArgumentException("Üres listának nincs átlaga."); }
int osszeg = 0;
foreach (int x in lista) { osszeg += x; }
return (double)osszeg / lista.Count;
}Mit tegyél ide: a nyomozónapló egy sora és a debug nézet a Jegy metódus else if során.Javasolt fájlnév: winforms-13-2-nyomozo.webp · Alt szöveg: A nyomozó-labor
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Tracepoint-napló
Egy ciklus 100-szor fut. Naplózd minden 10. lépés értékeit a kód módosítása nélkül. Tracepoint a ciklus testén: Hit Count: multiple of 10, Log a message: i = {i}, osszeg = {osszeg}, Continue execution bejelölve. Az eredmény az Output ablakban.Egy lehetséges megoldás
2. Hol hibás?
Egy program három metódust hív egymás után; a végeredmény rossz. Hogyan találod meg a hibásat kevés lépésből? Felezős keresés: töréspont a második metódus hívása elé; a bemenete helyes? Ha igen, a hiba a második vagy harmadik; ha nem, az első. Mindig a „még helyes” és a „már hibás” pont közé teszel töréspontot.Egy lehetséges megoldás
3. Saját hiba
Szúrj be egy logikai hibát egy korábbi programodba, és kérd meg valakit, hogy debuggerrel keresse meg. Jó, ha a hiba ritka feltételnél jelentkezik (negatív szám, üres lista, határérték), így a keresőnek feltételes töréspontra vagy tesztadat-gondolkodásra van szüksége.Egy lehetséges megoldás
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. F5 vagy Ctrl+F5?
Melyik áll meg a töréspontnál? Az F5 (debug módban indít); a Ctrl+F5 hibakereső nélkül.Megoldás megnyitása
2. Mikor áll meg?
A sor előtt vagy után áll meg a program a töréspontnál? A sor előtt: a megjelölt sor még nem hajtódott végre.Megoldás megnyitása
Közepes szint
3. F10 vagy F11?
Mikor melyiket? F10: ha a hívott metódust nem gyanítod; F11: ha belül akarsz nézni. Shift+F11: kilépés a metódusból.Megoldás megnyitása
4. Töréspont ciklusban
Hogyan állítod meg a programot a ciklus 250. lépésén? Feltételes töréspont (Megoldás megnyitása
i == 249), vagy Hit Count (= 250).
Kihívás szint
5. Tracepoint vagy MessageBox?
Miért jobb a tracepoint? Nem módosítja a kódot (nem kell utólag törölni), nem zavarja a felületet, nem állítja meg a programot, és sok adatot gyűjt.Megoldás megnyitása
6. A debug mellékhatása
Miért viselkedhet másképp a program debuggerrel, mint nélküle? Az időzítés megváltozik (megállás közben telik az idő: időzítők, időtúllépések), és a Debug és Release fordítás különbözik. Időfüggő hibákat naplózással (13.7 lecke) érdemes keresni.Megoldás megnyitása
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Egy sor, ahol a program megáll a futás közben, hogy megvizsgálhasd. Végrehajtja a sort (a hívott metódust is) egyben, és a következőn áll meg (F10). Belép a hívott metódusba (F11). Kilép a metódusból a hívóhoz (Shift+F11). Csak adott feltételnél áll meg (például egy ciklus egy adott lépésén). Töréspont, amely megállás nélkül üzenetet naplóz az Output ablakba. A gyanús rész előtt, ahol még minden rendben van.1. Mi a töréspont?
2. Mi a Step Over?
3. Mi a Step Into?
4. Mi a Step Out?
5. Mire jó a feltételes töréspont?
6. Mi a tracepoint?
7. Hol legyen a töréspont?
Mit tudsz már?
- Debug módban indítasz, és töréspontot teszel a megfelelő helyre.
- Helyesen választod a Step Over, Step Into és Step Out parancsot.
- Feltételes töréspontot és tracepointot használsz.
- Windows Forms eseménykezelőkben is lépésenként követed a futást.
Következő lecke: Locals, Watch és Call Stack
A megállított program belsejének vizsgálata: a változók értékei, saját kifejezések figyelése és a hívási lánc.


