Stivă și grămadă
Ca orice limbaj de programare sistem, Rust funcționează la un nivel scăzut. Dacă veniți dintr-un limbaj de nivel înalt, este posibil să nu fie familiarizați cu unele aspecte ale sistemului de programare. Cele mai importante sunt cele care se referă la memoria de lucru în stivă și grămadă. Dacă sunteți deja familiarizați cu alocarea de memorie mod este utilizat în limbaje cum ar fi C-în stivă, acest capitol se va actualiza cunoștințele. Dacă nu sunteți familiarizați cu acest lucru, în general, știi despre acest concept, dar cu accent pe Rust.
Acești doi termeni se referă la gestionarea memoriei. Stivă și heap - sunt abstractii care vă ajută să determinați atunci când trebuie să aloce și memorie deallocate.
Iată o comparație la nivel înalt.
Stiva este foarte rapid; Rust în memorie este alocată în stivă implicit. Izolarea memoriei stivă este locală la apelul funcției, și are o rezoluție limitată. Heap, pe de altă parte, este mai lent și alocarea de memorie pe heap este realizată în program explicit. Dar această memorie este teoretic dimensiuni nelimitate, și disponibile la nivel global.
Hai să vorbim despre următorul program pe Rust:
Acest program are un nume asociat, x. Memorie pentru el trebuie să fie undeva să aloce. default Rust „alocă memorie pe stivă“, ceea ce înseamnă că variabilele „sunt plasate pe stivă.“ Ce înseamnă?
Când funcția este numit, este alocată o anumită cantitate de memorie pentru toate variabilele sale locale și unele informații suplimentare. Aceasta se numește un „cadru de stivă» (frame stack). În acest ghid, vom ignora informațiile suplimentare, și considerăm doar variabilele locale pe care le definesc. Astfel, în acest caz, în care main (). vom selecta un număr întreg pe 32 de biți în cadrul nostru stivă. După cum puteți vedea, acest lucru se întâmplă în mod automat - nu trebuie să scrie nici un cod special pentru acest Rust.
Când se termină funcția, cadrul său stivă este eliberat. Acest lucru se întâmplă în mod automat - pentru aceasta nu avem nevoie să luați măsuri.
Asta e tot ce vine la acest program simplu. Principalul lucru este că aici trebuie să înțeleagă - este faptul că separarea stivei este foarte, foarte rapid. Deoarece toate variabilele locale ne sunt cunoscute în prealabil, putem aloca memorie pentru toate acestea dintr-o dată. Și, așa cum sunt, putem elibera foarte repede memoria alocată ca regulă, în același timp, du-te afara domeniului de aplicare.
Dezavantajul este că nu putem stoca valorile necesare pentru mai mult de o singură funcție.
Și totuși, noi nu vorbim despre ceea ce se numește „stivă“. Pentru a face acest lucru avem nevoie pentru a aduce un exemplu puțin mai complicat:
cadre stiva sunt utilizate nu numai pentru nume locale, ci și pentru argumentele. Astfel, în acest caz, cadrul nostru trebuie să conțină i. Argumentul nostru, astfel, și z. numele nostru local. i - o copie a argumentului y. Prin urmare, valoarea i. ca valoarea lui y. Acesta este 0.
Acesta este unul dintre motivele pentru adoptarea variabilei nu eliberează nici o valoare de referință de memorie este un pointer la zona de memorie. Dacă Lansăm localizat în memoria indicatorul, aceasta poate duce la erori în activitatea ulterioară.
Bine, să ia în considerare următoarele, pas program mai complex, cu pas:
În primul rând, noi numim main ():
Am aloca memorie pentru j. i. și h. i este alocat pe heap și deci conține un pointer la valoarea heap.
Mai mult, la sfârșitul apelului principal (). numit foo ():
Mai mult, foo () cauze Baz (). care trece z:
Am aloca memorie pentru f și g. Baz () este foarte scurt, iar când se termină, vom scăpa de cadrul său stivă:
foo suplimentară () determină bara () argumente x și z:
Aici vom evidenția o altă valoare pe gramada, asa ca scădem unul din (2 30) - 1. Această expresie este mai ușor să scrii decât 1073741 822. În orice caz, variabilele sunt ca de obicei.
La bara de capăt () cauzează Baz ():
Acum suntem la adâncimea cea mai mare! Felicitări pentru atingerea acestui punct.
După finalizarea Baz (). vom scăpa de g f și:
În continuare, vom efectua o întoarcere de la bar (). În acest caz, d este o cutie
Și atunci există o întoarcere de la foo ():
Și apoi, în cele din urmă, main (). care șterge orice altceva. Când a fost eliberat i (picătură), este de asemenea purificată și sfârșitul grămezii.
Cele mai multe limbi, cu colector de gunoi implicit alocă memorie din heap. Aceasta înseamnă că fiecare valoare va fi ambalate. Există mai multe motive pentru care este așa, dar ele sunt dincolo de domeniul de aplicare al acestui ghid. Există mai multe optimizări posibile, care, cu toate acestea, nu a atins scopul, în toate cazurile. În loc să se bazeze pe stivă și plasați pentru a șterge problemele de memorie, de colectare a gunoiului funcționează cu grămada.
Dar, în cazul în care stiva este mai rapid și mai ușor de gestionat, de ce ar trebui să existe o grămadă? Bine motiv este faptul că memoria pe stiva pot fi alocate doar pe un „primul venit - ultimul afară.“ Astfel, spațiul din cadrul anterior stiva apel funcție va refolosi sub următoarea provocare. Alocarea pe heap - o tehnică comună. Aceasta permite alocarea și Dealocarea în orice ordine. Cu toate acestea, acest lucru vine la costul de creșterea complexității punerii în aplicare a mecanismului de alocare de memorie.
În general, ar trebui să preferați izolarea în stivă, și, prin urmare, Rust utilizează selecția implicită în stivă. Modelul LIFO stivă ( „ultimul venit - primul out“) este fundamental mai simplu. Acest lucru înseamnă că programul este executat mai rapid și mai ușor în sens.
de gestionare a memoriei pentru un teanc banal: masina pur și simplu crește sau scade valoarea unuia, așa-numitul „stivă pointer» (stiva indicator). de gestionare a memoriei pentru heap complicat: memoria alocată în heap este eliberat uneori arbitrare, iar fiecare zonă este alocată pe memoria heap poate fi de dimensiuni arbitrare. Împărțitori tind să necesite mult mai mult efort pentru a identifica zonele care pot fi folosite din nou.
Alocarea memoriei în stivă Rust acționează ca limbă proprie, și în modelul de gândire de dezvoltare. semantica Stack - conceptul cheie al Rust. Obținem de management automat al memoriei fără a complica mediul de execuție. Acest mecanism vă permite să eliberați memorie pe heap, de îndată ce proprietarul său a ieșit din domeniul de aplicare - de fapt, a făcut implozie în cel mai scurt stivă cadru în care a trăit. Din păcate, în unele situații, stiva nu este suficient. Dacă aveți nevoie de mai multă flexibilitate în posesia memorie, puteți utiliza numărul de referință Rc
Dorința de a fi mai convenabil de a folosi memoria pe heap poate ajunge la extreme. Pe de o parte, este posibil să se pună în aplicare un colector de gunoi - dar crește foarte mult complexitatea mediului de execuție. Pe de altă parte, gestionarea memoriei manuală cu un proceduri de eliberare apel explicit de multe ori duce la greșeli, care au împiedicat Rust compilator nu se poate.
Putem prelungi durata de conservare prin transferul de proprietate, care este uneori numit „mișcarea pachetului» ( «mutarea din cutie»). Mai multe exemple complexe vor fi discutate mai târziu. # 8617;