Stack и купчина
Както и да е език за програмиране на системата, Rust работи на ниско ниво. Ако идвате от език на високо ниво, може да не сте запознати с някои аспекти от програмната система. Най-важните от тях са тези, които са свързани с работата памет в стека и куп. Ако вече сте запознати с разпределението на пътя памет се използва в C-подобен езици в стека, тази глава ще се опресни знанията си. Ако не сте запознати с тази, по принцип, което знаете за тази концепция, но с акцент върху ръжда.
Тези две условия са свързани с управлението на паметта. Стек и купчина - са абстракции, които да ви помогнат да се определи, когато трябва да се разпределят и преразпредели памет.
Ето сравнение на високо равнище.
Топчето е много бързо; Ръжда в паметта се разпределя в стека по подразбиране. Изолиране на паметта на стека е локално за извикване на функция, и е с ограничен резолюция. Heap, от друга страна, е по-бавен и разпределение на паметта на куп се извършва в програмата изрично. Но тази памет е теоретично неограничен размер, и в световен мащаб на разположение.
Нека поговорим за следващата програма на Rust:
Тази програма е една от име, х. Памет за него трябва да е някъде да се разпределят. Ръжда по подразбиране "заделя памет в стека", което означава, че променливите "са поставени в стека." Какво означава това?
При активиране на функцията се нарича, той се разпределя определено количество памет за всички свои локални променливи и допълнителна информация. Това се нарича "стека рамка» (стека рамка). В това ръководство, ние ще игнорира допълнителната информация, и смятаме, че само локалните променливи, които определят. Така, в този случай, когато основната (). ние изберете един 32-битово число в нашия стека рамка. Както можете да видите, това става автоматично - ние не трябва да напишете някакъв специален код за тази ръжда.
При активиране на функцията завършва, нейната стека рамка се освобождава. Това става автоматично - за това, че не е необходимо да предприемате никакви действия.
Това е всичко, което идва на тази проста програма. Основното нещо е, че тук трябва да се разбере - е, че разделянето на топчето е много, много бързо. Тъй като всички локални променливи се знае, че с нас предварително, можем да разпредели памет за всички от тях наведнъж. И тъй като те са, ние можем много бързо да освободи заделената памет като правило, в същото време да излезе от обхват.
Недостатъкът е, че не можем да се съхранява на изискваните стойности за повече от една функция.
И все пак ние не говорим за това, което се нарича "стека". За да направите това, което трябва да донесе малко по-сложно, например:
стак форми се използват не само за местни имена, но също така и за аргументите. По този начин, в този случай, нашата рамка трябва да съдържа аз. ни аргумент така и Z. нашето местно наименование. аз - копие от аргумент у. Следователно, стойността на т. като стойността на у. Той е 0.
Това е една от причините, поради приемането на променливата не освобождава всяко позоваване памет стойност е указател към зоната на паметта. Ако пуснем намира на паметта на показалеца, това може да доведе до грешки в по-нататъшната работа.
Добре, нека разгледаме следния, по-сложна стъпка програма по стъпка:
На първо място, ние наричаме главната ():
Ние памет за к. аз. и з. Аз се алокира и следователно съдържа указател към стойността на куп.
Освен това, в края на главната () повикване. наречен Foo ():
Освен това, Foo () предизвиква Баз (). преминаване Z:
Ние памет за е и ж. Баз () е много кратко, и когато тя свърши, ние се отърве от своя стак рамка:
Освен Foo () предизвиква бара () аргументи X и Z:
Тук ние се подчертае различна стойност на куп, така че ние се изважда един от (2 30) - 1. Този израз е по-лесно да се напише от 1073741 822. Във всеки случай, променливите са, както обикновено.
В края на лентата () предизвиква Баз ():
Сега ние сме на най-голяма дълбочина! Поздравления за достигането на тази точка.
След завършване Баз (). ние се отървете от е и ж:
След това, ние извършване на връщане от бар (). В този случай, г е Box
И тогава там е връщане от Foo ():
И тогава, най-накрая, основната (). който изчиства всичко останало. При пускането I (капка), и се пречиства и край на купчината.
Повечето езици с колектор подразбиране боклук заделя памет от куп. Това означава, че всяка стойност ще бъдат опаковани. Има няколко причини, защо това е така, но те са извън обхвата на това ръководство. Има няколко възможни оптимизации, които, обаче, не са достигнали целта си във всички случаи. Вместо да се разчита на комина и пуснете, за да изчистите проблемите с паметта, събиране на боклука работи с куп.
Но, ако топчето е по-бързо и по-лесно да се управлява, защо трябва да има един куп? Добра причина е, че паметта на стека може да се разпределя само на принципа "първи дошъл -. Миналата навън" По този начин, в пространството от предишната функция покана стека рамката ще използва повторно при следващото предизвикателство. Разпределяне на куп - обща техника. Тя позволява на разпределението и deallocation в произволен ред. Все пак, това е за сметка на увеличаване на сложността на изпълнение на механизма за разпределение на паметта.
Като цяло, трябва да се предпочитат изолацията в стека и следователно, Rust използва избора по подразбиране в стека. LIFO стека модел ( "Последният дойде - първа изходяща") е фундаментално по-просто. Това означава, че програмата се изпълнява по-бързо и по-лесно, в смисъл.
Управление на паметта на стека тривиално: колата просто увеличава или намалява стойността на един, така наречената "стека указател» (стека показалка). Управление на паметта за купчина сложно: паметта разпределени в купчината се освобождава при произволни пъти, а всяка област се разпределя върху паметта на купчина може да бъде произволен размер. Разпределители са склонни да се изисква много повече усилия, за да определят зоните, които могат да се използват отново.
заделяне на памет в стека действа като Rust собствения си език, а в модела на мислене за развитие. Стека семантика - ключовото понятие за ръжда. Получаваме автоматично управление на паметта, без да усложнява среда изпълнение. Този механизъм позволява да освободите памет на куп, веднага след като собственика си излезе от обхват - в действителност, веднага щом се самовзриви рамка стека, в която той живее. За съжаление, в някои ситуации, стека не е достатъчно. Ако имате нужда от по-голяма гъвкавост във владение на памет, можете да използвате този референтен брой Rc
В желанието си да бъде по-удобно да се използва паметта на куп може да достигне до крайности. От една страна, това е възможно да се направи събирач на боклук - но това значително увеличава сложността на средата за изпълнение. От друга страна, ръчно управление на паметта с процедурите Едно явно освобождаване разговор често води до грешки, които попречиха Rust компилатор не могат.
Ние можем да се удължи срокът на годност от прехвърляне на собствеността, което понякога се нарича "движението на пакетите» ( «движи извън кутията"). По-сложните примери ще бъдат обсъдени по-късно. # 8617;