Limbaj de programare cărți explica asta tipuri de valoare sunt create pe stiva, și tipuri de referință sunt create pe heap, fără a explica de ce aceste două lucruri sunt. Nu am't citit o explicație clară a acestui lucru. Am inteles ce e un stack_ este. Dar,
Stiva de memorie este rezervată ca spațiu zero pentru un fir de execuție. Atunci când o funcție este numit, un bloc este rezervat pe partea de sus de pe stivă pentru variabilele locale și unele datelor evidenței contabile. Când funcția returnează, blocul devine neutilizate și poate fi folosit data viitoare când o funcție este apelată. Stiva este întotdeauna rezervat în LIFO (last in first out) pentru; cel mai recent rezervate bloc este întotdeauna lângă bloc să fie eliberat. Acest lucru îl face foarte simplu pentru a ține evidența a stivei; eliberându-un bloc din stiva nu este nimic mai mult decât un singur indicator de reglare.
Heap este de memorie rezervată pentru alocarea dinamică. Spre deosebire de stiva, nu's nu executată model pentru alocarea și dealocarea de blocuri din heap; puteți aloca un bloc în orice moment și gratuit, în orice moment. Acest lucru face mult mai complexe pentru a ține evidența care părți ale heap sunt alocate sau gratuit, în orice moment; sunt multe personalizate morman de entitățile responsabile cu alocarea disponibilă pentru a acorda morman de performanță pentru diferite modele de utilizare.
Fiecare fir devine o stivă, în timp ce nu's, de obicei doar o grămadă de aplicare (deși nu e't mai puțin frecvente de a avea mai multe grămezi pentru diferite tipuri de alocare).
Pentru a răspunde la întrebările dumneavoastră direct:
To ce măsură sunt controlate de sistemul de OPERARE sau language runtime?
Sistemul de OPERARE alocă pe stivă pentru fiecare nivel de sistem de fir atunci când firul este creat. De obicei, sistemul de OPERARE este numit de către language runtime să aloce morman de aplicare.
What este domeniul de aplicare a acestora?
Stiva este atașat la un fir, astfel încât atunci când firul iese din stiva este regenerat. Heap este de obicei alocat la pornire de aplicare de execuție, și se strânge atunci când cererea (din punct de vedere tehnic procesul) ieșirile.
What determină dimensiunea de fiecare dintre ele?
Dimensiunea stivei este setat atunci când un fir de execuție este creat. Dimensiunea heap este setat la pornire de aplicare, dar poate creste ca este nevoie de spațiu (alocatorul solicită mai multă memorie de sistem de operare).
What face mai repede?
Stiva este mai rapid, deoarece accesul model face banal să aloce și deallocate memorie de ea (un pointer/număr întreg este pur și simplu incrementat sau decrementat), în timp ce heap are mult mai multe complexe de contabilitate implicat într-o alocare sau dealocarea. De asemenea, fiecare octet în stivă tinde să fie refolosite foarte frecvent, ceea ce înseamnă că tinde să fie mapate la procesor's, cache-ul, făcându-l foarte repede. Un alt hit de performanță pentru heap este că heap, fiind în mare parte o resursă globală, de obicei, trebuie să fie multi-threading în condiții de siguranță, adică fiecare alocarea și dealocarea trebuie să fie - de obicei - sincronizat cu "toate" alte heap accesează în program.
O demonstrație clară:
sursa Imaginii: vikashazrati.wordpress.com
Stiva:
Heap:
șterge
, delete[]
, sau "liber".malloc
respectiv.Exemplu:
int foo()
{
char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
bool b = true; // Allocated on the stack.
if(b)
{
//Create 500 bytes on the stack
char buffer[500];
//Create 500 bytes on the heap
pBuffer = new char[500];
}//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
Cel mai important este că heap și stiva sunt termeni generici pentru moduri în care memoria poate fi alocat. Ele pot fi puse în aplicare în mai multe moduri diferite, și termeni se aplică la conceptele de bază.
(Am mutat acest răspuns la o altă întrebare care a fost mai mult sau mai puțin o copie de pe acesta.) Răspunsul la întrebarea ta e specifice de implementare și poate varia de compilatoare și arhitecturi de procesor. Cu toate acestea, aici este o explicație simplificată.
malloc
) sunt îndeplinite prin crearea unui potrivite bloc de la unul dintre blocuri libere. Acest lucru necesită actualizarea lista de blocuri pe heap. Acest meta information despre blocurile de pe heap este, de asemenea, stocate pe grămada de multe ori într-o zonă mică în fața fiecărui bloc. Poate o funcția alocă în heap în loc de o stivă? Nu, activare registrele pentru funcții (de exemplu, locale sau automată variabile) sunt alocate pe stivă, care este folosit nu numai pentru a stoca aceste variabile, dar, de asemenea, pentru a urmări imbricate apeluri de funcții. Cum heap este gestionat este într-adevăr până la runtime environment. C foloseste
malloc
și C++ foloseste "noi", dar multe alte limbi au de colectare a gunoiului. Cu toate acestea, stiva este o mai scăzut nivel de caracteristică strâns legată de arhitectura de procesor. În creștere heap atunci când nu există suficient spațiu e't prea greu, deoarece acesta poate fi implementat în biblioteca de apel, care se ocupă de heap. Cu toate acestea, în creștere în stivă este de multe ori imposibil ca stack overflow numai este descoperit atunci când este prea târziu; și închiderea fir de execuție este singura opțiune viabilă.
În următoarele C# cod
public void Method1()
{
int i = 4;
int y = 2;
class1 cls1 = new class1();
}
Aici's cum memoria este reușit
`Variabile locale, că doar trebuie să dureze atâta timp cât funcția de invocare a merge în stivă. Heap este folosit pentru variabilele a căror viață nu ne't într-adevăr știu up față, dar le-am aștepta să dureze un timp. În cele mai multe limbi-l's critical care stim de la compilare cât de mare o variabilă este dacă vrem să-l stocați pe stiva.
Obiecte (care variază în dimensiune ca am update-i) merge pe heap pentru că nu ne't știu la crearea timp cât acestea sunt de gând să dureze. În multe limbi heap este gunoi colectate pentru a găsi obiecte (cum ar fi cls1 obiect) care nu mai avea nici o referire.
În Java, cele mai multe obiecte du-te direct în heap. În limbaje cum ar fi C / C++, struct și clase poate de multe ori rămân pe stiva atunci când te're de-a face cu indicii.
Mai multe informații pot fi găsite aici:
Diferența între stivă și heap alocare de memorie « timmurphy.org
și aici:
Crearea de Obiecte pe Stivă și Heap
Acest articol este sursa de imaginea de mai sus: Șase important .NET concepte: Stiva, heap, tipuri de valoare, tipurile de referință, boxing și unboxing - CodeProject
dar să fie conștienți că pot conține unele inadvertențe.
Stiva Atunci când apelați o funcție de argumentele pentru care funcția plus alte deasupra este pus pe stiva. Unele informații (cum ar fi în cazul în care pentru a merge pe retur) este, de asemenea, stocate acolo. Atunci când declarați o variabilă în interiorul funcției, variabila este, de asemenea, alocate pe stivă.
Deallocating stiva este destul de simplu, pentru că întotdeauna deallocate în ordinea inversă în care le aloca. Stiva de chestii se adaugă pe măsură ce introduceți funcții, datele corespunzătoare este eliminat după ieșirea ei. Acest lucru înseamnă că aveți tendința de a sta într-o mică regiune a stivei dacă nu ai sunat o mulțime de funcții care suna o mulțime de alte funcții (sau a crea o soluție recursivă).
Heap Heap este un nume generic pentru care ai pus datele pe care le creați pe zbor. Dacă tu nu't știu cât de multe nave spațiale programul tău este de gând să creați, vă sunt susceptibile de a utiliza noua (sau malloc sau echivalent) operatorul pentru a crea fiecare nava. Această alocare este de gând să stai în jurul pentru un timp, astfel încât este probabil ne va elibera lucrurile într-o ordine diferită decât le-am creat.
Astfel, heap este mult mai complexă, pentru că nu ajung să fie regiuni de memorie care sunt neutilizate intercalat cu bucati care sunt - memoria devine fragmentată. Găsirea liber de memorie de dimensiunea care aveți nevoie este o problemă dificilă. Acesta este motivul pentru heap ar trebui să fie evitate (deși este mai des utilizat).
Implementarea Punerea în aplicare a stiva și heap este, de obicei, până la execuție / OS. De multe ori jocuri și alte aplicații care sunt performanțele critică a crea propria lor memorie soluții care apuca o bucată mare de memorie din heap și apoi critici pe plan intern, pentru a evita bazându-se pe sistemul de OPERARE pentru memorie.
Aceasta este doar practic, dacă utilizarea de memorie este destul de diferit de norma - am.e pentru jocuri în cazul în care încărcați un nivel într-o singură operațiune uriașă și poate arunca totul departe într-o altă operațiune uriașă.
Locație fizică în memorie Acest lucru este mai puțin relevant decât crezi pentru că de o tehnologie numită Memorie Virtuală, ceea ce face programul tau cred ca ai acces la o anumită adresă în cazul în care datele fizice este în altă parte (chiar si pe hard disc!). Adresele pe care le obține pentru stivă sunt în ordine crescătoare ca suna copac devine mai profundă. Adresele pentru heap sunt ne-previzibil (am.e implimentation specifice) și sincer nu sunt importante.
Pentru a clarifica, acest răspuns are informații incorecte (toma a stabilit că răspunsul lui după comentarii, cool :) ). Alte răspunsuri doar pentru a evita explicarea a ceea ce statice de alocare a mijloacelor. Deci, voi explica cele trei forme principale de alocare și modul în care acestea se referă, de obicei la grămadă, stivă, și segmentul de date de mai jos. Am, de asemenea, vă va arăta câteva exemple în ambele C/C++ și Python pentru a ajuta oamenii să înțeleagă.
"Static" (AKA alocate static) variabile nu sunt alocate pe stivă. Nu presupune așa - mulți oameni nu numai din cauza "static" pare ca o "stiva". Ele există de fapt în nici stiva nici heap. Sunt o parte din ceea ce's, numit de segment de date.
Cu toate acestea, în general, este mai bine să ia în considerare "domeniul de aplicare" și "durata de viață" mai degrabă decât "stiva" și "rabla".
Domeniul de aplicare se referă la ceea ce părți ale codului posibilitatea de a accesa o variabilă. În general, ne gândim la local domeniul de aplicare (pot fi accesate numai de funcția actuală) versus aplicare la nivel mondial (pot fi accesate de oriunde), deși domeniul de aplicare poate obține mult mai complexe.
Durata de viață se referă la atunci când o variabilă este alocată și dezafectat în timpul execuției programului. De obicei ne gândim la statice de alocare (variabila va persista prin întreaga durată a programului, ceea ce face util pentru stocarea acelorași informații în mai multe apeluri de funcții) versus alocarea automată (variabila persistă doar în timpul unui apel la o funcție, făcându-l util pentru stocarea de informații, care este folosit numai în timpul funcției și pot fi eliminate odată ce ați terminat) versus alocare dinamică (variabile a căror durată este definit la runtime, în loc de compilare, cum ar fi static sau automatic).
Deși cele mai multe compilatoare și interpretoare pună în aplicare acest comportament similar în ceea ce privește utilizarea stive, grămezi, etc, un compilator poate rupe uneori aceste convenții dacă dorește atâta timp cât comportamentul este corect. De exemplu, din cauza optimizare o variabilă locală poate exista doar într-un registru sau să fie eliminate în întregime, chiar dacă cele mai multe variabilele locale există în stivă. Așa cum a fost subliniat în câteva comentarii, ești liber să pună în aplicare un compilator care nu't folosi chiar și o stivă sau o grămadă, dar în loc de alte mecanisme de stocare (rar făcut, deoarece stive și grămezile sunt foarte bune pentru acest lucru).
Eu va oferi un simplu adnotat cod C pentru a ilustra toate acestea. Cel mai bun mod de a învăța este de a rula un program sub un depanator și urmăriți comportamentul. Dacă preferați să citiți python, sări la sfârșitul răspunsul :)
// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;
// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed only within MyFunction()
static int someLocalStaticVariable;
// Allocated on the stack each time MyFunction is called
// Deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
int someLocalVariable;
// A *pointer* is allocated on the stack each time MyFunction is called
// This pointer is deallocated when MyFunction returns
// scope - the pointer can be accessed only within MyFunction()
int* someDynamicVariable;
// This line causes space for an integer to be allocated in the heap
// when this line is executed. Note this is not at the beginning of
// the call to MyFunction(), like the automatic variables
// scope - only code within MyFunction() can access this space
// *through this particular variable*.
// However, if you pass the address somewhere else, that code
// can access it too
someDynamicVariable = new int;
// This line deallocates the space for the integer in the heap.
// If we did not write it, the memory would be "leaked".
// Note a fundamental difference between the stack and heap
// the heap must be managed. The stack is managed for us.
delete someDynamicVariable;
// In other cases, instead of deallocating this heap space you
// might store the address somewhere more permanent to use later.
// Some languages even take care of deallocation for you... but
// always it needs to be taken care of at runtime by some mechanism.
// When the function returns, someArgument, someLocalVariable
// and the pointer someDynamicVariable are deallocated.
// The space pointed to by someDynamicVariable was already
// deallocated prior to returning.
return;
}
// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.
Un mod deosebit de pregnant exemplu de ce se's important să se facă distincția între viață și domeniul de aplicare este că o variabilă poate fi locale, domeniul de aplicare, dar static de viață - de exemplu, "someLocalStaticVariable" în exemplu de cod de mai sus. Astfel de variabile pot face noastre comune, dar informale denumire obiceiuri foarte confuz. De exemplu, atunci când spunem "locale" ne referim de obicei "la nivel local luneta alocate în mod automat variabila" și când spunem globală ne referim de obicei "la nivel global luneta static alocat variabilă". Din păcate, atunci când vine vorba de lucruri de genul "fișier luneta alocate static variabile" mulți oameni doar spun... "nu-i asa???".
Unele dintre sintaxa alegeri în C/C++ exacerba această problemă - de exemplu, mulți oameni cred că variabilele globale nu sunt "static" din cauza sintaxa prezentată mai jos.
int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation
int main() {return 0;}
Rețineți că punerea de cuvinte cheie "static" în declarația de mai sus previne var2 de a avea de aplicare la nivel mondial. Cu toate acestea, la nivel mondial var1 are statice de alocare. Acest lucru nu este intuitiv! Pentru acest motiv, încerc să nu folosesc cuvântul "static" atunci când descrie domeniul de aplicare, și în loc să spun ceva de genul "fișier" sau "fișier limitat" domeniul de aplicare. Cu toate acestea, mulți oameni folosesc expresia "static" sau "static domeniul de aplicare" pentru a descrie o variabilă care poate fi accesat numai de la un singur cod de fișier. În contextul de viață, "static" întotdeauna înseamnă variabilă este alocată la începutul programului și dealocate când termină programul.
Unii oameni cred că aceste concepte ca C/C++ specifice. Ele nu sunt. De exemplu, Python eșantion de mai jos ilustrează toate cele trei tipuri de alocare (există unele diferențe subtile posibil în interpretat de limbi pe care am câștigat - 't obține într aici).
from datetime import datetime
class Animal:
_FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated
def PetAnimal(self):
curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)
class Cat(Animal):
_FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's
class Dog(Animal):
_FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!
if __name__ == "__main__":
whiskers = Cat() # Dynamically allocated
fido = Dog() # Dynamically allocated
rinTinTin = Dog() # Dynamically allocated
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
Dog._FavoriteFood = 'milkbones'
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones
Alții au răspuns în linii mari, destul de bine, așa că am'll arunca în câteva detalii.
Stiva și heap trebuie să nu fie singular. O situație comună în care aveți mai mult de o stivă este dacă aveți mai mult de un singur fir într-un proces. În acest caz, fiecare fir are propria sa stivă. Puteți avea, de asemenea, mai mult de-o grămadă, de exemplu, unele DLL configurații pot duce la diferite Dll-uri alocarea din diferite grămezi, care este de ce-l's, în general, o idee rea pentru a elibera memoria alocată de către o altă bibliotecă.
În C puteți obține beneficii de lungime variabilă alocarea prin utilizarea de alocare, care alocă pe stivă, spre deosebire de alloc, care alocă în heap. Această memorie a câștigat't supraviețui declarație de întoarcere, dar's util pentru o zgârietură tampon.
Face o mare buffer temporar pe Windows care nu't folosi prea mult nu este gratuit. Aceasta deoarece compilatorul va genera un teanc sonda buclă, care este numit de fiecare dată când funcția este introdus pentru a asigurați-vă că topul există (pentru Windows utilizează o singură pagină de gardă la sfârșitul stack-ul tău pentru a detecta atunci când trebuie să crească stack. Dacă ai memorie cu acces mai mult de o pagină de pe la sfârșitul stivă se va prăbuși). Exemplu:
void myfunction()
{
char big[10000000];
// Do something that only uses for first 1K of big 99% of the time.
}
Alții au răspuns direct la întrebarea ta, dar atunci când încearcă să înțeleagă stivă și heap, cred că este util să se ia în considerare aspectul memorie tradițional de proces UNIX (fără fire și mmap ()
pe baza de repartitoare). De Management al Memoriei Glosar pagina web are o diagramă de această memorie layout.
Stiva și heap sunt în mod tradițional situat la capetele opuse ale procesului de's de spațiu de adrese virtuale. Stiva crește în mod automat atunci când este accesat, până la o dimensiune stabilită de nucleu (care pot fi ajustate cu setrlimit(RLIMIT_STACK, ...)). Grămada crește atunci când memoria repartitor invocă
brk () " sau " sbrk()` sistem de a apela, de cartografiere mai multe pagini de memorie fizică în procesul's de spațiu de adrese virtuale.
În sistemele fără memorie virtuală, cum ar fi unele sisteme integrate, același aspect de bază de multe ori se aplică, cu excepția stivă și heap au o dimensiune fixă. Cu toate acestea, în alte sisteme încorporate (cum ar fi cele bazate pe Microchip PIC microcontrolere), programul stivă este un bloc separat de memorie care nu este adresabil de date instrucțiunile de circulație, și nu poate fi modificat sau de a citi în mod indirect, prin programul de fluxul de instrucțiuni (apel, schimb, etc.). Alte arhitecturi, cum ar fi Intel Itanium procesoare, au mai multe stive. În acest sens, stiva este un element de arhitectura PROCESORULUI.
Stiva este o parte de memorie care poate fi manipulat prin intermediul mai multor cheie limbaj de asamblare instrucțiuni, cum ar fi 'pop' (scoateți și întoarce o valoare din stivă) și 'push' (împinge o valoare în stivă), dar, de asemenea, apel (call o subrutină - acest lucru îl împinge pe adresa de returnare pentru stivă) și retur (retur de la o subrutină - aceasta apare adresa de pe stivă și sare să-l). L's regiunea de memorie de mai jos indicatorul stivă registru, care poate fi setat după cum este necesar. Stiva este, de asemenea, folosit pentru transmiterea argumentelor la subrutine, și, de asemenea, pentru păstrarea valorilor în registre înainte de apelarea subrutinelor.
Heap este o parte de memorie care este dat la o cerere de sistemul de operare, de obicei, printr-un syscall ca malloc. Pe sisteme de operare moderne, această memorie este un set de pagini care procesul apelant are acces la.
Dimensiunea stivei este determinată în timpul rulării, și, în general, nu cresc după programul se lansează. Într-un program C, stiva trebuie să fie suficient de mare pentru a organiza fiecare variabilă declarată în fiecare funcție. Heap va crește în mod dinamic cum este necesar, dar sistemul de OPERARE este în cele din urmă de a face apel (de multe ori aceasta va crește grămadă de valoare mai mare decât cea solicitată de malloc, astfel încât cel puțin un viitor mallocs câștigat't nevoie pentru a merge înapoi pentru a kernel-ului pentru a obține mai multă memorie. Acest comportament este adesea personalizabil)
Pentru că tu'am alocat stivei înainte de lansarea programului, niciodată nu trebuie să malloc înainte de a putea utiliza stiva, astfel încât's un ușor avantaj acolo. În practică, se's foarte greu de prezis ce va fi și ce va fi lentă în sistemele de operare moderne, care au memorie virtuală a subsistemelor, pentru că modul în care paginile sunt puse în aplicare și în cazul în care acestea sunt stocate este o punere în aplicare detaliu.
Cred că multe alte persoane au dat cea mai mare răspunsuri corecte cu privire la această chestiune.
Un detaliu care a fost lipsit, cu toate acestea, este că "rabla" ar trebui, în fapt, fi, probabil, numit "magazin gratuit". Motivul pentru această distincție este faptul că inițial gratuit magazin a fost implementat cu o structură de date cunoscut ca un "heap binomial." Pentru acest motiv, alocarea de la începutul implementări de malloc()/free() a fost alocarea dintr-un heap. Cu toate acestea, în această zi moderne, cele mai multe magazine gratuite sunt puse în aplicare cu foarte elaborate structuri de date care nu sunt binom grămezi.
Ce este o stivă?
O stivă este o gramada de obiecte, de obicei cel care este frumos aranjat.
Stive în arhitecturi de calcul sunt regiuni de memorie în cazul în care datele sunt adăugate sau eliminate într-un last-in-first-out manieră.
Într-un multi-threaded de aplicare, fiecare fir va avea propria sa stivă.
Ce este un heap?
Un heap este un dezordonat colecție de lucruri îngrămădite la întâmplare.
În arhitecturi de calcul heap este un domeniu dinamic alocat de memorie care este gestionat în mod automat de către sistemul de operare sau managerul de memorie bibliotecă.
Memorie pe heap este alocat, dezafectat, și redimensionate în mod regulat în timpul execuției programului, iar acest lucru poate duce la o problema numita fragmentare.
Fragmentarea se produce atunci când obiecte de memorie sunt alocate cu mici spații între care sunt prea mici pentru a ține memorie suplimentară obiecte.
Rezultatul net este un procent de heap spațiul care nu este utilizabil pentru mai multe alocări de memorie.
Împreună
Într-un multi-threaded de aplicare, fiecare fir va avea propria sa stivă. Dar, toate diferite fire vor împărtăși heap.
Deoarece diferite fire partaja grămadă într-un multi-threaded de aplicare, acest lucru înseamnă, de asemenea, că trebuie să existe o coordonare între firele astfel încât acestea să nu încercați pentru a accesa și manipula aceeași bucată(e) de memorie în memoria heap, în același timp.
Care este mai rapid – stiva sau heap? Și de ce?
stiva este mult mai rapid decât heap.
Acest lucru este din cauza modului în care memoria este alocată pe stivă.
Alocarea de memorie pe stivă este la fel de simplu ca se deplasează indicatorul stivă în sus.
Pentru persoanele nou la programare, este, probabil, o idee bună de a folosi stiva, deoarece e mai ușor.
Pentru că stiva este mic, ce-ar vrea să-l folosească atunci când știi exact cât de mult de memorie ai avea nevoie pentru datele dvs., sau dacă știți dimensiunea de date este foarte mic.
Este mai bine să utilizați heap atunci când știți că veți avea nevoie de o mulțime de memorie pentru datele dvs., sau pur și simplu nu sunt sigur cât de mult de memorie ai avea nevoie (ca și cu o gamă dinamică).
Stiva este o zonă de memorie în cazul în care variabilele locale (inclusiv metoda parametrii) sunt stocate. Când vine vorba de variabile obiect, acestea sunt doar referințe (pointeri) la obiecte reale pe heap.
De fiecare dată când un obiect este instanțiată, o bucată de memorie heap este pus deoparte să dețină date (de stat) de acel obiect. Deoarece obiectele pot conține alte obiecte, unele dintre aceste date pot, în fapt, deține trimiteri la acele obiecte imbricate.
Puteți face unele lucruri interesante cu stiva. De exemplu, aveți funcții, cum ar fi alocare (presupunând că se poate trece de copios avertismente cu privire la utilizarea lor), care este o formă de malloc care utilizează în mod specific stiva, nu la grămadă, pentru memorie.
Asta a spus, stack-based erori de memorie sunt unele dintre cele mai grave I'am experimentat. Dacă utilizați memorie heap, și vă depășiți limitele alocate bloc, aveți o șansă decentă de a declanșa un segment de vina. (Nu 100%: bloc poate fi altfel învecinate cu un altul care trebuie alocate anterior.) Dar deoarece variabilele create pe stiva sunt întotdeauna învecinate cu fiecare alte, scris în afara limitelor poate schimba valoarea altei variabile. Am învățat că ori de câte ori simt că programul meu s-a oprit ascultarea de legile logicii, este, probabil, buffer overflow.
Pur și simplu, stiva este în cazul în care variabilele locale sunt create. De asemenea, de fiecare dată când apela o subrutină contor de program (pointer la următorul mașină de instrucțiuni) și de pe orice registre, și, uneori, parametrii împinși pe stiva. Atunci orice variabile locale în subrutina sunt împinse pe stiva (și utilizate de acolo). Când subrutina finisaje, astea toate se a întors de pe stivă. PC și registru de date se și pune acolo de unde a fost ca este aparut, deci programul poate merge pe drum vesel.
Heap este zona de memorie dinamică alocări de memorie sunt realizate din (explicit "noi" sau "aloca" apeluri). Este o structură specială de date, care pot urmări de blocuri de memorie de diferite dimensiuni și alocarea lor statut.
În "clasic" sisteme de RAM a fost stabilită astfel încât stack pointer început în jos de memorie heap pointer început în sus, și au crescut față de celălalt. Dacă acestea se suprapun, sunt în afara de RAM. Asta nu't de lucru modern, cu multi-threaded sisteme de operare, deși. Fiecare fir trebuie să aibă propria stivă, și acestea pot obține creat dynamicly.
Din WikiAnwser.
Atunci când o funcție sau o metodă solicită o altă funcție care se transformă într-solicită o altă funcție, etc., realizarea tuturor acestor funcții rămâne suspendat până în ultimul funcția returnează valoarea acestuia.
Acest lanț suspendate apeluri de funcții este stiva, deoarece elementele din stivă (apeluri de funcții) depind unele de altele.
Stiva este important să se ia în considerare în excepție de manipulare și fir de execuții.
Heap este pur și simplu de memorie utilizate de programe pentru a stoca variabile. Element din heap (variabile) nu au dependențe unul cu altul și pot fi oricând accesate aleator în orice moment.
Stiva
Heap
OK pur și simplu și în scurte cuvinte, ei spun ordonat și nu a ordonat...!
Stiva: În stiva de obiecte, lucrurile o iau pe partea de sus a reciproc, înseamnă că va fi mai rapid și mai eficient pentru a fi prelucrate!...
Deci, există întotdeauna un index de la punctul anumit element, de asemenea, de prelucrare va fi mai rapid, există o relație între elementele fel de bine!...
Heap: Nr. de ordine, de prelucrare va fi mai lent și valorile sunt amestecate împreună cu nici o ordine specifică sau index... sunt aleatoare și nu există nici o relație între ele... deci execuție și timpul de utilizare ar putea fi varia...
Am, de asemenea, de a crea imaginea de mai jos pentru a arăta cum se poate arata ca:
Acum vin la întrebarea ta's răspunsuri.
în ce măsură sunt controlate de sistemul de OPERARE sau language runtime? Sistemul de OPERARE alocă pe stivă pentru fiecare nivel de sistem de fir atunci când firul este creat. De obicei, sistemul de OPERARE este numit de către language runtime să aloce morman de aplicare. Mai pot fi găsite aici. care este scopul lor? Deja dat în sus. "puteți folosi stiva dacă știți exact cât de mult de date trebuie să aloce înainte de compilare, și nu este prea mare. Puteți utiliza grămadă, dacă nu't știu exact cât de mult datele pe care le va avea nevoie în timpul rulării sau dacă aveți nevoie să aloce o mulțime de date." Mai multe pot fi găsite în aici. ceea Ce determină dimensiunea de fiecare dintre ele? Dimensiunea stivei este setată de OS atunci când un fir de execuție este creat. Dimensiunea heap este setat la pornire de aplicare, dar poate să crească ca este nevoie de spațiu (alocatorul solicită mai multă memorie de sistem de operare). Ce face o mai repede? Stiva de alocare este mult mai rapid, deoarece totul este într-adevăr nu este de a muta indicatorul stivă. Folosind memorie liber, puteți obține performanțe comparabile din grămada de alocare, dar care vine cu o ușoară adăugat complexitate și de propriile dureri de cap. De asemenea, stiva vs heap este nu numai o performanță considerare; de asemenea, vă spune o mulțime de lucruri despre viață preconizată de obiecte. Detalii pot fi găsite la aici.
În anii 1980, UNIX-a propagat ca iepurași cu marile companii de rulare a lor. Exxon a avut una ca a facut zeci de nume de brand pierdut în istorie. Cum de memorie a fost pus a fost la discreția mulți implementatori.
Tipic pentru un program C-a fost întinsă în memorie cu o oportunitate de a crește prin schimbarea brk() valoare. De obicei, HEAP a fost chiar sub această valoare brk și creșterea brk a crescut cantitatea de disponibil heap.
Single STACK era de obicei o zonă de mai jos HEAP, care a fost un tract de memorie conțin nimic de valoare până la partea de sus de lângă bloc fix de memorie. Următorul bloc a fost de multe ori un COD care ar putea fi suprascrise de stiva de date într-una din celebrele hacks de epoca sa.
Unul tipic bloc de memorie a fost BSS (un bloc de valori de zero) care a fost accidental, nu se aduce la zero într-un singur producator's oferă. Un alt fost DATE conțin inițializat valori, inclusiv siruri de caractere și numere. Un al treilea era un COD care conține CRT (C runtime), principal, funcții și biblioteci.
Apariția de memorie virtuală în UNIX modificările multe constrângeri. Nu există nici un motiv obiectiv pentru care aceste blocuri trebuie să fie învecinate, sau o dimensiune fixă, sau comandat un mod special acum. Desigur, înainte de UNIX a fost Multics care nu't suferă de aceste constrângeri. Aici este o schemă care arată unul dintre memorie machete din acea epoca.