2. praktikum - Stacki vaatlemine

Allikas: Lambda
Süsteemprogrammeerimine keeles C

Praktikumid

Laborid

Selle praktikumi eesmärk on avastada call stack ja seda veidi lahata.

NB! Tänast harjutust teeme klassi arvutites, sest Dijkstra on ümberehitamisel.

Ülesanne

Meie töömeetod on järgmine: kirjutame programmi, milles on hulk muutujaid ning seejärel proovime aru saada kuidas nad mällu asetuvad. Selleks kasutame pointereid ja eelmise praktikumi mälu tõlgendamise kohta õpitut.

Programm

Kirjutage programm mille funktsioonis main() on deklareeritud:

  • vähemalt 3 täisarvulist muutujat erinevate vaikimisi väärtustega,
  • string

Lisage programmile funktsioon foo(int i), milles on deklareeritud:

  • vähemalt 2 erinevat täisarvulist muutujat vaikimisi väärtustatult,

See programm ei pea otseselt midagi tegema, aga funktsioon foo() võiks käivituda.

Uurimine

  • Täienda programmi nii, et ta trükib välja kõigi muutujate mäluaadressid (printf() funktsiooni asendustähisena %p tõlgendab mäluaadressi mõistlikult). Muutuja muudab aadressiks tehe &.
  • Vaata funktsioonis foo() esimese deklareeritud muutuja ees ja selle taga olevaid mäluaadresse. (Kindlas kohas mälu vaatamiseks kasuta * tehet).
  • Kas on võimalik minna kaugemale? Kas foo sees leitud aadressi muutmisel on võimalik leida funktsiooni main() muutujad? (On, aga proovi seda teha ja vihjena: nende pointerite aadresside lahutamisel saadud tulemus peaks olema alati sama)
  • Kas string main() funktsioonis paikneb ka stackis?
  • Püüdke funktsioonis foo() rikkuda funktsioonide main() ja foo() kohalike muutujate vahel olevad andmed ning oma programm seeläbi kokku jooksutada.
  • Kommenteeri välja ühe main() muutuja kõik viited. Jälgi, et su programm neid ei kasutaks -- kas neid on ka pärast seda foo() alt leitud mäluaadressi abil võimalik vaadata?
  • Lisa mõnele muutujale võtmesõna static ning kontrolli tema olemasolu.
  • Taasta muutujate seis. Kirjuta funktsioon, mis püüab kogu stacki välja trükkida (4 baiti iga printf() väljakutse kohta, "%08x\n" näiteks. Võib olla kasulik trükkida välja ka muutuja tõlgendus kümnendsüsteemis ja 4 erineva charina.) Kuna tahame näha mis on mälus pärast stacki lõppu, on programmi vältimatu kokkujooksmine ainult teretulnud!


Järeldused

Labori lõpuks peaksime mõistma seda kuivõrd paindlikult saame mäluga ümber käia. Loodetavasti on sellest kasu mõnede mõistatustlike kokkujooksmiste taga olevate põhjuste avastamisel. Keeltes, milledes pointerid puuduvad on stack olemas, kuid programmeerija jaoks vaadeldav vaid silumisvahendiga. Sealjuures tulemegi stacki teemade juurde debuggerit uurides korra tagasi.