A gdb-ba történő hibakeresés, hogyan lehet elolvasni egy változóhoz vagy egy osztály kívánt tulajdonságához való hivatkozást (cikkek -

A program használata kdbg (a felület a debugger gdb), azt követte a logikáját a programot, és megállapította, hogy bizonyos ponton védett, néhány tulajdonságát egyik objektum kezdenek tartalmazhatnak érvénytelen értékeket, és ezáltal torzított logika. Ezeknek a tulajdonságoknak nincs beállítója a nebylo kódban. Az ingatlan értéke mutatott bizonyos körülmények között az osztályban, és a lehetséges értékeket szigorúan korlátozott. És azok az értékek, amelyeket megfigyeltem, nagyon különböznek a lehetségesektől.
Problémás volt, hogy egyes kódok adatokat írtak a helytelen memóriaterületen. Általában ez akkor történik, ha elhagyod a tömböt.
Sajnos az interneten található meglévő anyagok kevéssé mondják el, hogyan kell hibakeresni az osztályokat és tulajdonságokat tartalmazó gdb C ++ programokban. Ezért meg kellett érteni a meg nem éretteket.
A kdbg környezetben nézõpontokat lehet beállítani, de valójában nem kdbg-ban dolgoznak. A hibakeresést a gdb konzolban kellett végrehajtani. mert az ellenőrzési pontok a várt módon működnek. Feltételezzük, hogy az olvasó ismeri a gdb hibakeresés alapjait. tudja meghatározni a töréspontokat, végrehajtani a programot lépésekben, és tudja megnézni a változók értékeit.
Tehát a tervezőben vagyunk. Segítünk abban, hogy ez az érték bármelyik konstruktorban ismert, mivel az osztály létrehozott példányára vonatkozó memóriát mindig előre kiosztják.
A "tiszta" gdb-ben meg kell adnia a parancsot:
> print this.counter
Ezekkel a parancsokkal megtanultam a változó értékét, és a kdbg esetében a név helyes írásmódját.
> nyomtatás (This.counter)
Általában véve észrevettem, hogy a "tiszta" gdb-ben nem feltétlenül kell a C / C ++ szintaxisban kifejezett kifejezéseket írni. Például a "->" karakterek helyettesíthetők a ".", És a "*" írása a mutató típusáról való tájékoztatáshoz szintén opcionális. Ez egyszerűsíti a hibakeresést.
Egy tulajdonság lehet egy mutató egy alap típusú vagy mutatóhoz egy másik objektumhoz (az alábbiakban tárgyaljuk). Ebben az esetben a cselekvések megegyeznek! Egyszerűen, ha a tervezőben van, akkor szükség van rá, ha a mutatót inicializálni szeretné. Ezután kattintson rá a jobb egérgombbal, válassza a "Watch expression" lehetőséget. A megfigyelések területén egy sor jelenik meg:
Ez a sor bővíthető, és benne van a mutató által hivatkozott érték.
Gyakran előfordul, hogy egy probléma-változó egy olyan tulajdonságban van, amely egy objektum. És már ebben az objektumban probléma van.
Ebben az esetben lépésről lépésre meg kell kezdeni az objektum tulajdonságának inicializálását. Ezután a "változó" fát fel lehet bővíteni a kívánt változóra, és ugyanúgy a jobb egérgombbal válaszd a "Watch expression" kifejezést. A megfigyelések területén egy sor jelenik meg:
A "tiszta" gdb-ben ugyanazon műveleteknél megadhatja a parancsot:
> print this.window.active
+-> (bool *) aktív 0x859f161
Ezenkívül feltételezzük, hogy a hibakeresés a gdb-hez érkezik, mivel a kdbg nézõpontok vannak, de nem működnek.
Azt feltételezik, hogy van egy osztály változó Stapp pWindow típus „mutatót az objektum STWindow”, és ennek az objektumnak STWindow bool változó bSleep. Ennek a változónak az értéke egy ponton elkényeztetett. Meg kell fogni a pillanatot, és nézd meg a kódot, hogy meghamisítja az adatokat.
A töréspontot az STApp osztály kivitelezőjének első utasítására helyezzük. Futtassa a programot végrehajtásra. A lépésenkénti leállítás után elérjük azt a pontot, amelyen a pWindow objektumot inicializáljuk. Ezután győződjön meg arról, hogy az inicializálás rendben volt:
$ 1 = (STApp * const) 0xbffff284
(gdb) kinyomtatja ezt
$ 2 = (STWindow * osztály) 0x859ee10
(gdb) kinyomtatja ezt az ablakot
A forráskód alapján ítélve a bSleep változó kezdetben hamis. így rendben van.
(gdb) nyomtatás (This.pWindow.bSleep)
$ 4 = (bool *) 0x859f161
(gdb) nézni * ((int *) 0x859f161)
2. hardver figyelőpont: * ((int *) 0x859f161)
Ellenőrizzük, hogy ezt az órát hogyan adtuk hozzá:
Num Type Disp Enb Cím Mi
1 breakpoint megtartja az y 0x08070fa8 értéket a STApp :: STApp (int, char **)
a töréspont már 1 alkalommal ütközött
2 hw figyelőpontot tartani y * ((int *) 0x859f161)
A program két megszakítását látjuk: az első megszakítás egy normál töréspont, amely nekünk dolgozott. A második megszakítás az éppen létrehozott hardveres figyelőpont.
Amikor az óra működött
Miután beállította az órát, a folytatás parancsot adjuk meg. így a program folytatja a végrehajtását. És egy bizonyos ponton a gdb leállítja a program végrehajtását:
2. hardver figyelőpont: * ((int *) 0x859f161)
Régi érték = 1409833472
Új érték = 1413336268
gombra :: számítás (ez = 0x859f160, deltaT = 0.100000001)
14 fLastPressed + = deltaT;
Lássuk, mi a kód a 14. sor mellett:
üres gomb: számítás (float deltaT)
Aha, nyilvánvalóan, az osztály gomb egy bizonyos objektuma valahol a bSleep közelében található. és fLastPressed tárolásakor. írja ezt az értéket, ahol a bSleep fekszik. Lássuk a híváscsomagot:
# 0 gomb :: számít (ez = 0x859f160, deltaT = 0.100000001)
a /St/Window/button.cpp:14 mappában
# 1 0xb644d5a3 a STBaseWindow :: compute (ez = 0x859ee10, deltaT = 0,100000001)
a /St/Window/stWindowsSDL.cpp:423 címen
# 2 0xb642d2b6 az STSceneGraph :: render_scene (ez = 0xb1fda008)
a /St/Render/SceneGraph/stSceneGraph.cpp:412 könyvtárban
# 3 0xb6437106 az STSceneGraphSlot :: render_scene (ez = 0xb1fda008)
a /St/Render/SceneGraph/stSceneGraphSlot.cpp:138 címen
# 4 0x08070b82 a STApp :: Idle (ez = 0xbffff284)
a /St.2.0/Game/stApp.cpp:39 címen
# 5 0xb644db65 a STBaseWindow :: MainLoop (ez = 0x859ee10)
a /St/Window/stWindowsSDL.cpp:275 címen
# 6 0xb63ff42c az App :: hurokban (ez = 0xbffff284)
a /St/Application/app.cpp:49 oldalon
# 7 0x08071c71 a STApp :: Run-ban (ez = 0xbffff284, argc = 1, argv = 0xbffff364)
a /St.2.0/Game/stApp.cpp:495 címen
# 8 0x08073280 fő (argc = 1, argv = 0xbffff364)
a /St.2.0/Game/stMain.cpp:13 címen
Nézzük meg a kódot, amely a button :: compute () metódust hívja. a hívásstallumból származó információk szerint itt található: /St/Window/stWindowsSDL.cpp:423. Ez a kód így néz ki:
az (int c = 0; c<25;c++ )
dEmulattionButton [c] .compute (deltaT);
dButtons [c] .compute (deltaT);
>
Aha, tárgyak tömbjei. És a "mágikus állandó" 25. És mi a dimenziója ezeknek a tömböknek? A /St/Window/stWindowsSDL.h fejlécfájlban megtaláljuk a következő kódot:
gomb dButtons [24];
gomb dEmulattionButton [24];
.
Ismét a "mágikus konstans", de ezúttal 24. Azt hiszem, minden világos - egy klasszikus barlang van mágikus konstansokkal és egy kiút a tömbből.
Így megtudtuk, mi a probléma, és nem lenne nehéz megoldani.
A Linuxban egy furcsa hagyomány szerint a programok neve gyakran emberileg olvasható. Ezért felhívom a figyelmet arra, hogy a konzol hibakeresőjét gdb - G nu D eB uggernek hívják. És a grafikus KDE-felületet kdbg - K de D eB ugG ernek hívják. Ez azt jelenti, hogy a gdb elején a g nu jelentése G, és a végén a kdbg jelenti a G er utótagot. Ne tévessze össze az írást.
Minden jó szerencsét és hibás programokat.