de Tiago Antunes

Cum să înțelegeți memoria programului dvs.

Când codificați într-un limbaj precum C sau C ++, puteți interacționa cu memoria într-un mod mai scăzut. Uneori, acest lucru creează o mulțime de probleme pe care nu le întâmpinați înainte: segfaults. Aceste erori sunt destul de enervante și vă pot cauza multe probleme. Acestea sunt adesea indicatori că folosiți memorie pe care nu ar trebui să o utilizați.

Una dintre cele mai frecvente probleme este accesarea memoriei care a fost deja eliberată. Aceasta este memoria cu care ați lansat free, sau memorie pe care programul dvs. a eliberat-o automat, de exemplu din stivă.

Înțelegerea tuturor acestor lucruri este foarte simplă și cu siguranță vă va face să programați mai bine și într-un mod mai inteligent.

Cum este împărțită memoria?

Cum sa intelegeti memoria programului dvs
High înseamnă adrese mari

Memoria este împărțită în mai multe segmente. Două dintre cele mai importante, pentru acest post, sunt grămadă și morman. Stiva este un loc de inserare ordonat, în timp ce heap-ul este aleatoriu – alocați memorie oriunde puteți.

Memoria stivă are un set de modalități și operațiuni pentru munca sa. Acolo se salvează unele informații despre registrele procesorului dvs. Și acolo sunt informațiile relevante despre programul dvs. – ce funcții sunt numite, ce variabile ați creat și câteva informații suplimentare. Această memorie este gestionată și de program și nu de către dezvoltator.

Heap-ul este adesea folosit pentru a aloca cantități mari de memorie care ar trebui să existe atât timp cât dorește dezvoltatorul. Acestea fiind spuse, este sarcina dezvoltatorului de a controla utilizarea memoriei pe heap. Atunci când construiți programe complexe, trebuie adesea să alocați bucăți mari de memorie și de aici folosiți heap-ul. Noi numim asta Memorie dinamică.

Plasați lucruri pe grămadă de fiecare dată când utilizați malloc să aloce memorie pentru ceva. Orice alt apel care merge ca. int i; este memoria stivei. Știind acest lucru este foarte important, astfel încât să puteți găsi cu ușurință erori în programul dvs. și să îmbunătățiți în continuare căutarea de erori Segfault.

Înțelegerea stivei

Deși este posibil să nu știți despre asta, programul dvs. alocă în mod constant memorie stivă pentru ca aceasta să funcționeze. Fiecare variabilă locală și fiecare funcție pe care o apelați merge acolo. Cu aceasta, puteți face o mulțime de lucruri – cele mai multe dintre ele sunt lucruri pe care nu ați dorit să se întâmple – cum ar fi depășirea bufferului și accesarea memoriei incorecte.

Deci, cum funcționează cu adevărat?

Stiva este o structură de date LIFO (Last-In-First-Out). O puteți vizualiza ca o cutie de cărți perfect potrivite – ultima carte pe care o plasați este prima pe care o scoateți. Prin utilizarea acestei structuri, programul își poate gestiona cu ușurință toate operațiunile și domeniile, utilizând două operații simple: Apăsați și pop.

Aceștia doi fac exact opusul unul altuia. Push introduce valoarea în partea de sus a stivei. Pop ia cea mai mare valoare din aceasta.

1612168987 481 Cum sa intelegeti memoria programului dvs
Operații Push și Pop.

Pentru a urmări locul memoriei curente, există un registru special al procesorului numit Stack Pointer. De fiecare dată când trebuie să salvați ceva – cum ar fi o variabilă sau adresa de returnare dintr-o funcție – acesta împinge și deplasează indicatorul stivei în sus. De fiecare dată când ieșiți dintr-o funcție, apare totul de la indicatorul stivei până la adresa de returnare salvată din funcție. E simplu!

Pentru a testa dacă ați înțeles, să folosim următorul exemplu (încercați să găsiți singur eroarea ☺️):

Cum sa intelegeti memoria programului dvs
Totul pare ok – până îl rulați.

Dacă îl rulați, programul va fi pur și simplu separat. De ce se întâmplă asta? Totul arată la locul său! Cu excepția cam … stivei.

Când apelăm funcția createArray, stiva:

  • salvează adresa de retur,
  • creează arr în memoria stivei și o returnează (o matrice este pur și simplu un pointer către o locație de memorie cu informațiile sale)
  • dar din moment ce nu am folosit malloc se salvează în memoria stivei.

După ce returnăm indicatorul, deoarece nu avem niciun control asupra operațiilor stivei, programul scoate informațiile din stivă și le folosește după cum are nevoie. Când încercăm să completăm matricea după ce ne-am întors din funcție, corupem memoria – făcând ca programul să fie separat.

Înțelegerea grămezii

În opoziție cu stiva, heap-ul este ceea ce utilizați atunci când doriți să existe ceva de ceva timp, independent de funcții și domenii. Pentru a utiliza această memorie, limbajul C. stdlib este foarte bun, deoarece aduce două funcții minunate: malloc și free.

Malloc (alocarea memoriei) solicită sistemului cantitatea de memorie solicitată și returnează un indicator la adresa de pornire. Liber spune sistemului că memoria pe care am solicitat-o ​​nu mai este necesară și poate fi utilizată pentru alte sarcini. Arată foarte simplu – atâta timp cât eviți greșelile.

Sistemul nu poate suprascrie ceea ce au cerut dezvoltatorii. Deci, depinde de noi, oamenii, să o gestionăm cu cele două funcții de mai sus. Aceasta deschide ușa unei erori umane: Scurgerile de memorie.

Memory Leak este memoria solicitată de utilizator, care nu a fost niciodată eliberată – când programul s-a încheiat sau au fost pierdute indicațiile către locațiile sale. Acest lucru face ca programul să folosească mult mai multă memorie decât ceea ce trebuia. Pentru a evita acest lucru, de fiecare dată când nu mai avem nevoie de un element alocat heap, îl eliberăm.

1612168988 41 Cum sa intelegeti memoria programului dvs
Indicații: rău vs bun.

În imaginea de mai sus, modul rău nu eliberează niciodată memoria pe care am folosit-o. Acest lucru ajunge să irosească 20 * 4 octeți (dimensiunea int în 64 de biți) = 80 octeți. Acest lucru s-ar putea să nu arate atât de mult, dar imaginați-vă că nu faceți acest lucru într-un program uriaș. Putem ajunge să irosim gigaocteți!

Gestionarea memoriei heap este esențială pentru eficientizarea memoriei programelor. Dar trebuie, de asemenea, să fii atent la modul în care îl folosești. La fel ca în memoria stivei, după ce memoria este eliberată, accesarea acesteia sau utilizarea acesteia vă pot provoca un defect.

Bonus: Structuri și grămada

Una dintre greșelile obișnuite atunci când se utilizează structuri este doar eliberarea structurii. Este în regulă, atâta timp cât nu am alocat memorie pointerilor din struct. Dacă memoria este alocată pointerilor din struct, trebuie mai întâi să le eliberăm. Apoi putem elibera întreaga structură.

1612168988 499 Cum sa intelegeti memoria programului dvs
Uită-te la modul în care am folosit gratuit

Cum îmi rezolv problemele de scurgere a memoriei

De cele mai multe ori când programez în C, folosesc structuri. Prin urmare, am întotdeauna două funcții obligatorii de utilizat cu structurile mele: constructor si destructor.

Aceste două funcții sunt singurele în care folosesc mallocs și liber pe struct. Acest lucru face cu adevărat simplu și ușor să-mi rezolv scurgerile de memorie.

(Dacă doriți să aflați mai multe despre simplificarea citirii codului, verificați postarea mea despre abstractizare).

1612168988 186 Cum sa intelegeti memoria programului dvs
O modalitate de a crea și o modalitate de a distruge!

Un instrument excelent de gestionare a memoriei – Valgrind

Este greu să vă gestionați memoria și să vă asigurați că ați gestionat totul corect. Un instrument excelent pentru a valida dacă programul dvs. se comportă corect este Valgrind. Acest instrument vă validează programul, spunându-vă câtă memorie ați alocat, cât ați eliberat, dacă ați încercat să scrieți într-o zonă de memorie incorectă … Utilizarea acestuia este o modalitate excelentă de a valida dacă totul este în regulă și ar trebui să o folosiți pentru a evita compromisuri de securitate.

1612168989 546 Cum sa intelegeti memoria programului dvs
Un exemplu de utilizare a valgrind, oferindu-vă informații despre ceea ce nu a funcționat corect

Nu uitați să mă urmați!

Pe lângă postarea aici pe Medium, sunt și pe Stare de nervozitate.

Dacă aveți întrebări sau sugestii, nu ezitați să mă contactați.