Ohjelman muistin ymmärtäminen

Kun koodaat kielellä, kuten C tai C ++, voit olla vuorovaikutuksessa muistisi kanssa matalammalla tasolla. Joskus tämä aiheuttaa paljon ongelmia, joita et aiemmin saanut: segfaults. Nämä virheet ovat melko ärsyttäviä ja voivat aiheuttaa paljon ongelmia. Ne ovat usein osoitus siitä, että käytät muistia, jota sinun ei pitäisi käyttää.

Yksi yleisimmistä ongelmista on jo vapautetun muistin käyttö. Tämä on muisti, jonka olet joko vapauttanut ilmaiseksi, tai muisti, jonka ohjelmasi on automaattisesti vapauttanut, esimerkiksi pinosta.

Kaiken tämän ymmärtäminen on todella helppoa ja se tekee sinusta ehdottomasti paremman ja älykkäämmän ohjelmoinnin.

Kuinka muisti on jaettu?

Korkea tarkoittaa korkeaa osoitetta

Muisti on jaettu useisiin segmentteihin. Kaksi tämän viestin tärkeintä ovat pino ja kasa. Pino on tilattu lisäyspaikka koko kasan ollessa satunnainen - varaat muistin missä vain.

Pino-muistilla on joukko tapoja ja toimintoja työhönsä. Siinä osa prosessorin rekisteröintitiedoista tallennetaan. Ja sinne minne menee asiaankuuluvat tiedot ohjelmassasi - mitä toimintoja kutsutaan, mitkä muuttujat olet luonut ja joitain lisätietoja. Tätä muistia hallinnoi myös ohjelma, ei kehittäjä.

Kasa käytetään usein varaamaan suuria määriä muistia, joiden oletetaan olevan olemassa niin kauan kuin kehittäjä haluaa. Toisin sanoen, kehittäjän tehtävänä on hallita kasan muistin käyttöä. Kun rakennat monimutkaisia ​​ohjelmia, joudut usein varaamaan suuria muistin osia, ja siinä käytät kasaa. Kutsumme tätä dynaamiseksi muistiksi.

Laitat asiat kasaan joka kerta, kun käytät malloc-muistia jonkin muistin varaamiseen. Kaikki muut puhelut, jotka menevät kuin int i; on pinon muisti. Tämän tietäminen on todella tärkeää, jotta löydät helposti virheet ohjelmasta ja parannat edelleen Segfault-virhehakuasi.

Pino ymmärtäminen

Vaikka et ehkä tiedä siitä, ohjelmasi varaa jatkuvasti pino-muistia sen toimimiseksi. Jokainen paikallinen muuttuja ja jokainen toiminto, johon soitat, menevät sinne. Tämän avulla voit tehdä paljon asioita - useimmat niistä ovat asioita, joita et halunnut tapahtua - kuten puskurin ylivuodot ja väärän muistin käyttö.

Joten miten se todella toimii?

Pino on LIFO (viimeinen ensimmäisenä-ulos) -rakenne. Voit tarkastella sitä täydellisesti asennettujen kirjojen laatikkona - viimeinen kirjoittamasi kirja on ensimmäinen, jonka otat ulos. Tätä rakennetta käyttämällä ohjelma voi helposti hallita kaikkia toimintojaan ja laajuuksiaan käyttämällä kahta yksinkertaista toimintoa: push ja pop.

Nämä kaksi tekevät täysin päinvastaisia ​​toisiinsa. Push lisää arvon pinon yläosaan. Pop ottaa siitä arvon.

Push- ja Pop-toiminnot.

Nykyisen muistipaikan seuraamiseksi on olemassa erityinen prosessorirekisteri nimeltään Stack Pointer. Aina, kun joudut tallentamaan jotain - kuten muuttujaa tai funktion palautusosoitetta -, se työntää ja siirtää pinon osoittimen ylöspäin. Aina kun poistut toiminnosta, se hyppää kaiken pino-osoittimesta toiminnon tallennettuun palautusosoitteeseen. Se on yksinkertaista!

Käytämme seuraavaa esimerkkiä testataksesi ymmärtääksesi ymmärtääksesi (yritä löytää vika yksin ):

Kaikki näyttää hyvältä - kunnes suoritat sen.

Jos suoritat sen, ohjelma yksinkertaisesti segmentoi. Miksi näin tapahtuu? Kaikki näyttää paikallaan! Paitsi noin ... pino.

Kun kutsumme funktiota createArray, pino:

  • tallentaa palautusosoitteen,
  • luo arr pinon muistiin ja palauttaa sen (taulukko on yksinkertaisesti osoitin muistipaikkaan sen tietojen kanssa)
  • mutta koska emme käyttäneet malloc-sovellusta, se tallennetaan pino-muistiin.

Kun palautamme osoittimen, koska meillä ei ole hallintaa pinotoiminnoista, ohjelma hyppää pinossa olevat tiedot ja käyttää niitä tarvittaessa. Kun yritämme täyttää taulukon palaamisen jälkeen toiminnosta, vioitamme muistia - tekemällä ohjelmasta oletusarvon.

Ymmärtäminen kasaan

Pinoa vasten kasa on mitä käytät, kun haluat jonkin olevan olemassa jonkin aikaa toiminnoista ja laajuudesta riippumatta. Tämän muistin käyttämiseksi C-kielen stdlib on todella hyvä, koska se tuo kaksi mahtavaa toimintoa: malloc ja ilmaisen.

Malloc (muistin varaus) pyytää järjestelmää pyydetyn muistin määrän ja palauttaa osoittimen aloitusosoitteeseen. Free kertoo järjestelmälle, että pyydettyä muistia ei enää tarvita ja sitä voidaan käyttää muihin tehtäviin. Näyttää todella yksinkertaiselta - kunhan vältät virheitä.

Järjestelmä ei voi ohittaa sitä, mitä kehittäjät vaativat. Joten meistä ihmisistä riippuu hallita sitä kahdella yllä olevalla toiminnolla. Tämä avaa oven yhdelle inhimilliselle virheelle: Memory Leaks.

Muistivuoto on käyttäjän pyytämä muisti, jota ei koskaan vapautettu - kun ohjelma päättyi tai osoittimet sen sijaintiin kadotettiin. Tämä saa ohjelman käyttämään paljon enemmän muistia kuin mitä sen piti olla. Tämän välttämiseksi vapautamme sen joka kerta, kun emme enää tarvitse kasaan varattua elementtiä.

Osoittimet: huono vs hyvä.

Yllä olevassa kuvassa huono tapa ei koskaan vapauta käyttämäämme muistia. Tämä lopulta tuhlaa 20 * 4 tavua (int-koko 64-bittinä) = 80 tavua. Tämä ei ehkä näytä niin kovalta, mutta kuvitelkaa, että et tee tätä jättiläisohjelmassa. Voimme lopulta tuhlata gigatavua!

Kasan muistin hallinta on välttämätöntä, jotta ohjelmien muisti on tehokas. Mutta sinun on myös oltava varovainen käyttäessäsi sitä. Aivan kuten pino-muistissa, sen jälkeen, kun muisti on vapautettu, sen käyttäminen tai käyttäminen voi aiheuttaa segmentin.

Bonus: Raot ja kasa

Yksi yleisimmistä virheistä, kun käytetään rakenteita, on vain vapauttaa rakenne. Tämä on hienoa, kunhan emme allokoineet muistia rakenteen sisällä oleviin osoittimiin. Jos muisti on osoitettu rakenteen sisällä oleville osoittimille, meidän on ensin vapautettava ne. Sitten voimme vapauttaa koko rakenteen.

Katso kuinka käytin ilmaiseksi

Kuinka voin ratkaista muistin vuoto-ongelmat

Ohjelmoidessani C-tilassa käytän suurimmaksi osaksi rakenteita. Siksi minulla on aina kaksi pakollista toimintoa käytettäväksi rakenteideni kanssa: rakentaja ja tuhoaja.

Nämä kaksi toimintoa ovat ainoat, joissa käytän mallokkeja ja vapautan rakenteessa. Tämän ansiosta muistivuotojen ratkaiseminen on todella helppoa ja helppoa.

(Jos haluat tietää enemmän koodin helpottamisesta lukemista, tarkista viestini abstraktiosta).

Tapa luoda ja tapa tuhota!

Upea muistinhallintatyökalu - Valgrind

Muistia on vaikea hallita ja varmistaa, että käsitteit kaikkea oikein. Valgrind on erinomainen työkalu vahvistaaksesi, toimiiko ohjelmasi oikein. Tämä työkalu vahvistaa ohjelman ja kertoo sinulle, kuinka paljon muistia olet allokoinut, kuinka paljon vapautunut, jos yritit kirjoittaa väärälle muistialueelle… Sen käyttäminen on loistava tapa vahvistaa, onko kaikki kunnossa, ja sitä tulisi käyttää välttämään turvallisuuskompromissit.

Esimerkki valgrindin käytöstä, antaa sinulle tietoja siitä, mikä meni pieleen

Älä unohda seurata minua!

Sen lisäksi, että postitan täällä Mediumille, olen myös Twitterissä.

Jos sinulla on kysyttävää tai ehdotuksia, ota rohkeasti yhteyttä minuun.