25 Domanda: Cosa e dove sono lo stack e l'heap?

domanda creata a Wed, Apr 10, 2019 12:00 AM

I libri di lingua di programmazione spiegano che i tipi di valore vengono creati nello stack e i tipi di riferimento sono creati nello heap , senza spiegare quali sono queste due cose. Non ho letto una spiegazione chiara di questo. Capisco cosa uno stack è. Ma,

  • Dove e cosa sono (fisicamente nella memoria di un vero computer)?
  • In che misura sono controllati dal sistema operativo o dal tempo di esecuzione della lingua?
  • Qual è il loro scopo?
  • Che cosa determina la dimensione di ciascuno di essi?
  • Cosa rende più veloce?
7663
  1. una spiegazione veramente buona può essere trovata qui Qual è la differenza tra uno stack e un heap?
    2013-12-16 11: 32: 49Z
  2. Anche (veramente) buono: codeproject.com/Articles/76153/... (la parte stack /heap)
    2014-02-15 05: 50: 34Z
  3. 2016-06-11 05: 42: 54Z
  4. Relativo, vedere Stack Clash . Le riparazioni di Stack Clash hanno interessato alcuni aspetti delle variabili di sistema e comportamenti come rlimit_stack. Vedi anche Red Hat Numero 1463241
    2017-06-21 16: 23: 19Z
  5. @ mattshane Le definizioni di stack e heap non dipendono dal tipo di valore e dai tipi di riferimento. In altre parole, lo stack e l'heap possono essere completamente definiti anche se i tipi di valore e riferimento non sono mai esistiti. Inoltre, quando si comprendono il valore e i tipi di riferimento, lo stack è solo un dettaglio di implementazione. Per Eric Lippert: Lo stack è un dettaglio di implementazione, prima parte .
    2017-11-12 22: 38: 03Z
25 risposte                              25                         

Lo stack è la memoria riservata come spazio zero per un thread di esecuzione. Quando viene chiamata una funzione, un blocco è riservato in cima allo stack per le variabili locali e alcuni dati contabili. Quando viene restituita la funzione, il blocco non viene utilizzato e può essere utilizzato la volta successiva che viene chiamata una funzione. Lo stack è sempre riservato in un ordine LIFO (last in first out); il blocco riservato più di recente è sempre il blocco successivo da liberare. Questo rende molto semplice tenere traccia dello stack; liberare un blocco dallo stack non è altro che regolare un puntatore.

L'heap è memoria riservata per l'allocazione dinamica. A differenza dello stack, non esiste un modello forzato per l'allocazione e la deallocazione dei blocchi dall'heap; puoi allocare un blocco in qualsiasi momento e liberarlo in qualsiasi momento. Ciò rende molto più complesso tenere traccia di quali parti dell'heap sono allocate o libere in un dato momento; ci sono molti allocatori di heap personalizzati disponibili per ottimizzare le prestazioni dell'heap per diversi modelli di utilizzo.

Ogni thread riceve uno stack, mentre in genere c'è solo un heap per l'applicazione (sebbene non sia raro avere più heap per diversi tipi di allocazione).

Per rispondere direttamente alle tue domande:

  

In che misura sono controllati dal sistema operativo o dal runtime della lingua?

Il sistema operativo alloca lo stack per ogni thread a livello di sistema quando thil thread è stato creato. In genere il sistema operativo viene chiamato dal runtime della lingua per allocare l'heap per l'applicazione.

  

Qual è il loro scopo?

Lo stack è collegato a un thread, quindi quando il thread esce lo stack viene recuperato. L'heap viene in genere assegnato all'avvio dell'applicazione dal runtime ed è recuperato quando l'applicazione (tecnicamente di processo) termina.

  

Cosa determina la dimensione di ognuno di essi?

La dimensione dello stack è impostata quando viene creato un thread. La dimensione dell'heap è impostata all'avvio dell'applicazione, ma può aumentare man mano che lo spazio è necessario (l'allocatore richiede più memoria dal sistema operativo).

  

Cosa rende più veloce?

Lo stack è più veloce perché il pattern di accesso rende banale allocare e deallocare memoria da esso (un puntatore /intero viene semplicemente incrementato o decrementato), mentre l'heap ha una contabilità molto più complessa coinvolta in un'allocazione o deallocazione. Inoltre, ogni byte nello stack tende a essere riutilizzato molto frequentemente, il che significa che tende a essere mappato alla cache del processore, rendendolo molto veloce. Un altro problema di prestazioni per l'heap è che l'heap, essendo in gran parte una risorsa globale, di solito deve essere multi-threading sicuro, vale a dire che ogni allocazione e deallocazione deve essere tipicamente sincronizzata con "tutti" altri accessi al programma nel programma. /p>

Una dimostrazione chiara:
Fonte immagine: vikashazrati.wordpress.com

    
5652
2016-05-02 12: 35: 48Z
  1. Buona risposta - ma penso che dovresti aggiungere che mentre lo stack è allocato dal sistema operativo all'avvio del processo (presupponendo l'esistenza di un sistema operativo), viene mantenuto in linea dal programma. Questo è un altro motivo per cui lo stack è più veloce: le operazioni push e pop sono in genere un'istruzione machine e le macchine moderne possono eseguire almeno 3 di esse in un ciclo, mentre allocare o liberare heap implica chiamare nel codice OS.
    2013-10-08 08: 31: 45Z
  2. Sono davvero confuso dal diagramma alla fine. Pensavo di averlo ottenuto fino a quando non ho visto quell'immagine.
    2016-08-15 19: 06: 04Z
  3. @ Anarelle il processore esegue le istruzioni con o senza un os. Un esempio vicino al mio cuore è il SNES, che non ha avuto chiamate API, nessun SO come lo conosciamo oggi - ma aveva uno stack. L'allocazione in pila è addizione e sottrazione su questi sistemi e va bene per le variabili distrutte quando vengono spuntate tornando dalla funzione che le ha create, ma costruite ciò, per esempio, in un costruttore, il cui risultato non può essere solo gettato via. Per questo abbiamo bisogno dell'heap, che non è legato alla chiamata e al ritorno. La maggior parte dei sistemi operativi ha un API in pila, nessun motivo per farlo da solo
    15-10-2016 15: 06: 55Z
  4. "stack è la memoria messa da parte come scratch space". Freddo. Ma dove è effettivamente "messo da parte" in termini di struttura della memoria Java ?? Memoria heap /Memoria non heap /Altro (struttura memoria Java come betsol.com/2017/06/... )
    2018-07-22 06: 22: 38Z
  5. @ JatinShashoo Java runtime, come interprete bytecode, aggiunge un ulteriore livello di virtualizzazione, quindi ciò a cui si fa riferimento è solo il punto di vista dell'applicazione Java. Dal punto di vista del sistema operativo tutto ciò è solo un heap, in cui il processo di runtime Java assegna parte del suo spazio come memoria "non-heap" per bytecode elaborato. Il resto dell'heap a livello di sistema operativo viene utilizzato come heap a livello di applicazione, dove vengono archiviati i dati dell'oggetto.
    2018-09-06 15: 41: 48Z

Stack:

  • Memorizzato nella RAM del computer proprio come l'heap.
  • Variabili createnello stack andrà fuori campo e viene automaticamente deallocato.
  • Molto più veloce da allocare rispetto alle variabili sullo heap.
  • Implementato con una struttura di dati dello stack effettiva.
  • Memorizza i dati locali, restituisce gli indirizzi, utilizzati per il passaggio dei parametri.
  • Può avere uno stack overflow quando viene usato troppo stack (principalmente da ricorsione infinita o troppo profonda, allocazioni molto grandi).
  • I dati creati nello stack possono essere utilizzati senza puntatori.
  • Utilizzerai lo stack se sai esattamente quanti dati hai bisogno di allocare prima della compilazione e non è troppo grande.
  • Di solito ha una dimensione massima già determinata all'avvio del programma.

Heap:

  • Memorizzato nella RAM del computer proprio come lo stack.
  • In C ++, le variabili sullo heap devono essere distrutte manualmente e non devono mai essere escluse dall'ambito. I dati vengono liberati con delete, delete[] o free.
  • Più lento da allocare rispetto alle variabili nello stack.
  • Usato su richiesta per allocare un blocco di dati per l'utilizzo da parte del programma.
  • Può avere una frammentazione quando ci sono molte allocazioni e deallocations.
  • In C ++ o C, i dati creati nell'heap saranno puntati da puntatori e allocati rispettivamente con new o malloc.
  • Può avere errori di allocazione se è richiesto l'allocazione di un buffer troppo grande.
  • Utilizzerai l'heap se non sai esattamente quanti dati avrai bisogno in fase di esecuzione o se devi allocare molti dati.
  • Responsabile delle perdite di memoria.

Esempio:

 
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;
    
2237
2017-07-28 00: 38: 33Z
  1. Il puntatore pBuffer e il valore di b si trovano nello stack e sono per lo più allocati all'entrata della funzione. A seconda del compilatore, anche il buffer può essere assegnato all'ingresso della funzione.
    2009-03-18 22: 48: 52Z
  2. È un malinteso comune il linguaggio C, come definito dallo standard di linguaggio C99 (disponibile in open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf ), richiede un "pila". In effetti, la parola "stack" non appare nemmeno nello standard. Questo risponde alle istruzioni wrt /to l'uso dello stack di C è vero in generale, ma non è in alcun modo richiesto dalla lingua. Vedi knosof.co.uk/cbook/cbook.html per maggiori informazioni, e in particolare come il C è implementato su architetture a sfera dispari come en.wikipedia.org/wiki/Burroughs_large_systems
    2009-09-01 04: 37: 30Z
  3. @ Brian Devi spiegare perché buffer [] e il puntatore pBuffer vengono creati nello stack e perché i dati di pBuffer vengono creati nell'heap. Penso che alcuni ppl potrebbero essere confusi dalla tua risposta in quanto potrebbero pensare che il programma stia specificando che la memoria sia allocata nello stack o nell'heap ma questo non è il caso. È perché Buffer è un tipo di valore mentre pBuffer è un tipo di riferimento?
    2010-02-08 04: 56: 47Z
  4. @ Remover: nessun puntatore contiene un indirizzo e può puntare a qualcosa sull'heap o sullo stack allo stesso modo. nuovo, malloc e alcune altre funzioni simili a quelle di malloc allocano sullo heap e restituiscono l'indirizzo della memoria allocata. Perché dovresti allocare sull'heap? In modo che la tua memoria non vada fuori campo e non venga rilasciata fino a quando non lo desideri.
    2012-05-26 23: 25: 58Z
  5. "Responsabile delle perdite di memoria" - Heaps non è responsabile delle perdite di memoria! I codificatori /codificatori pigri /dimentichi /ex-java che non danno una schifezza sono!
    2013-03-25 08: 22: 06Z

Il punto più importante è che heap e stack sono termini generici per i modi in cui la memoria può essere allocatated. Possono essere implementati in molti modi diversi e i termini si applicano ai concetti di base.

  • In una pila di oggetti, gli oggetti sono posti l'uno sopra l'altro nell'ordine in cui sono stati posizionati lì, e puoi rimuovere solo quello superiore (senza rovesciare l'intero oggetto).

    Impila come una pila di fogli

    La semplicità di uno stack è che non è necessario mantenere una tabella contenente un record di ciascuna sezione della memoria allocata; l'unica informazione di stato di cui hai bisogno è un singolo puntatore alla fine dello stack. Per allocare e de-allocare, basta incrementare e decrementare quel singolo puntatore. Nota: a volte può essere implementato uno stack per iniziare nella parte superiore di una sezione della memoria ed estendersi verso il basso anziché crescere verso l'alto.

  • In un heap, non c'è un ordine particolare nel modo in cui gli oggetti sono posizionati. Puoi raggiungere e rimuovere elementi in qualsiasi ordine perché non esiste un elemento "top" chiaro.

    Ammassa come un mucchio di liquirizia allsorts

    L'allocazione degli heap richiede il mantenimento di una registrazione completa della memoria allocata e di ciò che non lo è, oltre a una manutenzione generale per ridurre la frammentazione, trovare segmenti di memoria contigui abbastanza grandi da adattarsi alla dimensione richiesta e così via. La memoria può essere dislocata in qualsiasi momento lasciando spazio libero. A volte un allocatore di memoria eseguirà attività di manutenzione come la deframmentazione della memoria spostando la memoria allocata intorno o la raccolta dei dati inutili, identificando in fase di esecuzione quando la memoria non è più in ambito e la rilascia.

Queste immagini dovrebbero fare un buon lavoro nel descrivere i due modi di allocare e liberare memoria in uno stack e un heap. Yum!

  • In che misura sono controllati dal sistema operativo o dal runtime della lingua?

    Come già detto, heap e stack sono termini generali e possono essere implementati in molti modi. I programmi per computer in genere hanno uno stack chiamato stack di chiamate che memorizza informazioni rilevanti per la funzione corrente come puntatore a qualsiasi funzione da cui è stato chiamato e qualsiasi variabile locale. Poiché le funzioni richiamano altre funzioni e quindi restituiscono, lo stack aumenta e si restringe per contenere le informazioni dalle funzioni più in basso nello stack di chiamate. Un programma in realtà non ha il controllo di runtime su di esso; è determinato dal linguaggio di programmazione, dal sistema operativo e persino dall'architettura del sistema.

    Un heap è un termine generico usato per qualsiasi memoria allocata dinamicamente e in modo casuale; cioè fuori uso. La memoria viene in genere allocata dal sistema operativo, con l'applicazione che chiama le funzioni API per eseguire questa allocazione. C'è un bel po 'di overhead richiesto nella gestione della memoria allocata dinamicamente, che viene solitamente gestita dal sistema operativo.

  • Qual è il loro scopo?

    Lo stack di chiamate è un concetto di basso livello che non si riferisce a "scope" nel senso della programmazione. Se si disassembla un po 'di codice, si vedranno i riferimenti relativi allo stile del puntatore a porzioni dello stack, ma per quanto riguarda un linguaggio di livello superiore, il linguaggio impone le proprie regole di ambito. Un aspetto importante di uno stack, tuttavia, è che una volta restituita una funzione, qualsiasi elemento locale a quella funzione viene immediatamente liberato dallo stack. Funziona come ti aspetteresti che funzioni, visto come funzionano i tuoi linguaggi di programmazione. In un heap, è anche difficile da definire. L'ambito è quello che viene esposto dal sistema operativo, ma il linguaggio di programmazione probabilmente aggiunge le sue regole su cosa sia un "ambito" nell'applicazione. L'architettura del processore e il sistema operativo utilizzano l'indirizzamento virtuale, che il processore traduce in indirizzi fisici e ci sono errori di pagina, ecc. Essi tengono traccia di quali pagine appartengono a quali applicazioni. Non devi mai preoccuparti di questo, però, perché usi solo il metodo utilizzato dal tuo linguaggio di programmazione per allocare e liberare memoria, e controlla gli errori (se l'allocazione /liberazione fallisce per qualsiasi motivo).

  • Che cosa determina la dimensione di ciascuno di essi?

    Di nuovo, dipende dalla lingua, dal compilatore, dal sistema operativo e dall'architettura. Solitamente uno stack viene pre-allocato, perché per definizione deve essere una memoria contigua (più su questo nell'ultimo paragrafo). Il compilatore di lingue o il sistema operativo determinano le sue dimensioni. Non si immagazzinano enormi quantità di dati nello stack, quindi sarà abbastanza grande da non essere mai utilizzato completamente, tranne nei casi di ricorsione infinita indesiderata (quindi, "stack overflow") o altre decisioni di programmazione insolite.

    Un heap è un termine generico per tutto ciò che può essere assegnato dinamicamente. A seconda del modo in cui lo guardi, cambia costantemente dimensione. Nei moderni processori e sistemi operativi il modo esatto in cui funziona è comunque molto astratto, quindi non è necessariopreoccuparsi molto di come funziona in profondità, tranne che (nelle lingue in cui ti lascia) non devi usare la memoria che non hai ancora assegnato o la memoria che hai liberato.

  • Che cosa rende più veloce?

    Lo stack è più veloce perché tutta la memoria libera è sempre contigua. Nessuna lista deve essere mantenuta di tutti i segmenti della memoria libera, solo un singolo puntatore alla cima corrente dello stack. Generalmente, i compilatori memorizzano questo puntatore in un registro speciale e veloce per questo scopo. Inoltre, le operazioni successive su uno stack sono solitamente concentrate in aree molto vicine della memoria, che a un livello molto basso sono utili per l'ottimizzazione dalle cache del processore on-die.

1323
2017-12-17 22: 26: 52Z
  1. David Non sono d'accordo sul fatto che sia una buona immagine o che "stack di push down" sia un buon termine per illustrare il concetto. Quando aggiungi qualcosa a uno stack, gli altri contenuti dello stack non sono spostati verso il basso, rimangono dove sono.
    2012-08-13 03: 40: 14Z
  2. Questa risposta include un grosso errore. Le variabili statiche non sono allocate nello stack. Vedi la mia risposta [collegamento] stackoverflow.com/a/13326916/1763801 per chiarimenti. stai equipaggiando variabili "automatiche" con variabili "statiche", ma non sono affatto uguali
    2012-11-10 23: 07: 01Z
  3. In particolare, si dice "le variabili locali allocate staticamente" sono allocate nello stack. In realtà sono allocati nel segmento dati. Solo le variabili allocate automaticamente (che includono la maggior parte ma non tutte le variabili locali e anche cose come i parametri di funzione passati per valore piuttosto che per riferimento) sono allocate nello stack.
    2012-11-11 01: 44: 52Z
  4. Mi sono appena reso conto che hai ragione - in C, l'allocazione statica è una sua cosa separata piuttosto che un termine per tutto ciò che non è dinamica . Ho modificato la mia risposta, grazie.
    2012-11-12 00: 29: 15Z
  5. Non è solo C. Java, Pascal, Python e molti altri hanno tutte le nozioni di allocazione statica rispetto a quella automatica rispetto a quella dinamica. Dire "allocazione statica" significa la stessa cosa ovunque. In nessuna lingua l'allocazione statica significa "non dinamica". Vuoi il termine allocazione "automatica" per ciò che stai descrivendo (cioè le cose nello stack).
    2012-11-12 17: 16: 28Z

(Ho spostato questa risposta da un'altra domanda che era più o meno un dupe di questo.)

La risposta alla tua domanda è specifica dell'implementazione e può variare tra compilatori e architetture di processore. Tuttavia, ecco una spiegazione semplificata.

  • Sia lo stack che l'heap sono aree di memoria allocate dal sistema operativo sottostante (spesso memoria virtuale mappata alla memoria fisica su richiesta).
  • In un ambiente multi-threading ogni thread avrà il proprio stack completamente indipendente ma condivideranno l'heap. L'accesso simultaneo deve essere controllato sull'heap e non è possibile sullo stack.

L'heap

  • L'heap contiene un elenco collegato di blocchi usati e liberi. Le nuove allocazioni nello heap (di new o malloc) vengono soddisfatte creando un blocco adatto da uno dei blocchi liberi. Ciò richiede l'aggiornamento dell'elenco di blocchi nell'heap. Questa meta informazione dei blocchi sull'heap è anche memorizzata nell'heap spesso in una piccola area di fronte a ogni blocco.
  • Man mano che l'heap cresce, i nuovi blocchi vengono spesso assegnati da indirizzi inferiori a indirizzi superiori. Quindi puoi pensare all'heap come un heap di blocchi di memoria che cresce di dimensioni man mano che la memoria viene allocata. Se l'heap è troppo piccolo per un'allocazione, le dimensioni possono essere spesso aumentate acquisendo più memoria dal sistema operativo sottostante.
  • Allocazione e deallocazione di moltipiccoli blocchi possono lasciare l'heap in uno stato in cui sono presenti molti piccoli blocchi liberi intervallati tra i blocchi utilizzati. Una richiesta di allocare un blocco di grandi dimensioni potrebbe non riuscire perché nessuno dei blocchi liberi è sufficientemente grande da soddisfare la richiesta di allocazione anche se la dimensione combinata dei blocchi liberi potrebbe essere abbastanza grande. Questa è chiamata frammentazione dell'heap .
  • Quando un blocco utilizzato adiacente a un blocco libero viene deallocato, il nuovo blocco libero può essere unito al blocco libero adiacente per creare un blocco libero più grande che riduce effettivamente la frammentazione dell'heap.

L'heap

Lo stack

  • Lo stack lavora spesso in stretto tandem con uno speciale registro sulla CPU chiamato stack pointer . Inizialmente il puntatore dello stack punta in cima allo stack (l'indirizzo più alto nello stack).
  • La CPU ha istruzioni speciali per premere valori sullo stack e scoppiare di nuovo dallo stack. Ogni push memorizza il valore nella posizione corrente del puntatore dello stack e diminuisce il puntatore dello stack. Un pop recupera il valore puntato dal puntatore dello stack e quindi aumenta il puntatore dello stack (non essere confuso dal fatto che aggiungendo un valore allo stack diminuisce il puntatore dello stack e rimuove un valore aumenta ​​em>. Ricorda che lo stack aumenta fino in fondo). I valori memorizzati e recuperati sono i valori dei registri della CPU.
  • Quando viene chiamata una funzione, la CPU usa istruzioni speciali che spingono il puntatore di istruzioni corrente, cioè l'indirizzo del codice che si sta eseguendo nello stack. La CPU quindi salta alla funzione impostando il puntatore di istruzioni all'indirizzo della funzione chiamata. Successivamente, quando la funzione ritorna, il vecchio puntatore di istruzioni viene estratto dallo stack e l'esecuzione riprende dal codice subito dopo la chiamata alla funzione.
  • Quando si inserisce una funzione, il puntatore dello stack viene diminuito per allocare più spazio nello stack per le variabili locali (automatiche). Se la funzione ha una variabile locale a 32 bit, quattro byte vengono messi da parte nello stack. Quando la funzione ritorna, il puntatore dello stack viene spostato indietro per liberare l'area allocata.
  • Se una funzione ha parametri, questi vengono inseriti nello stack prima della chiamata alla funzione. Il codice nella funzione è quindi in grado di spostarsi verso l'alto dallo stack dal puntatore dello stack corrente per individuare questi valori.
  • Le chiamate alle funzioni di nidificazione funzionano come un incantesimo. Ogni nuova chiamata allocherà i parametri di funzione, l'indirizzo di ritorno e lo spazio per le variabili locali e questi record di attivazione possono essere impilati per le chiamate annidate e si svolgeranno nel modo corretto quando le funzioni ritornano.
  • Poiché lo stack è un blocco limitato di memoria, è possibile causare un overflow dello stack chiamando troppe funzioni annidate e /o allocando troppo spazio per le variabili locali. Spesso l'area di memoria utilizzata per lo stack è impostata in modo tale che la scrittura al di sotto del fondo (l'indirizzo più basso) dello stack attiverà un trap o un'eccezione nella CPU. Questa condizione eccezionale può quindi essere catturata dal runtime e convertita in una sorta di eccezione di overflow dello stack.

Lo stack

  

È possibile allocare una funzione sull'heap anziché su uno stack?

No, i record di attivazione per le funzioni (cioè le variabili locali o automatiche) sono allocati nello stack che viene utilizzato non solo per memorizzare queste variabili, ma anche per tenere traccia delle chiamate di funzioni annidate.

Il modo in cui viene gestito l'heap dipende in realtà dall'ambiente di runtime. C usa malloc e C ++ usa new, ma molte altre lingue hanno la garbage collection.

Tuttavia, lo stack è una funzionalità di livello più basso strettamente legata all'architettura del processore. Crescere l'heap quando non c'è abbastanza spazio non è troppo difficile poiché può essere implementato nella chiamata alla libreria che gestisce l'heap. Tuttavia, la crescita dello stack è spesso impossibile in quanto l'overflow dello stack viene scoperto solo quando è troppo tardi; e l'interruzione del thread di esecuzione è l'unica opzione valida.

    
695
2012-03-28 23: 03: 30Z
  1. @ Martin - Una risposta /spiegazione molto buona rispetto alla risposta più astratta accettata. Un esempio di programma di assemblaggio che mostra i puntatori /registri dello stack utilizzati per le chiamate alla funzione vis sarà più illustrativo.
    2012-04-25 16: 42: 17Z
  2. Ogni tipo di riferimentoè la composizione dei tipi di valore (int, string ecc.). Come si dice, quei tipi di valore sono memorizzati nello stack di come funziona quando fanno parte del tipo di riferimento.
    2014-02-15 10: 26: 30Z
  3. Questa risposta è stata la migliore, secondo me, perché mi ha aiutato a capire che cos'è una dichiarazione di ritorno e in che modo si riferisce a questo "indirizzo di ritorno" che trovo ogni di tanto in tanto, cosa significa spingere una funzione nello stack e perché le funzioni vengono spinte su pile. Ottima risposta!
    2014-03-19 19: 59: 21Z
  4. Questo è il migliore secondo me, vale a dire che l'heap /stack è molto specifico per l'implementazione. Le altre risposte presuppongono un lotto di cose sulla lingua e sull'ambiente /OS. 1
    2014-11-29 02: 00: 15Z
  5. Cosa intendi "Il codice nella funzione è quindi in grado di spostarsi verso l'alto dalla pila dal puntatore dello stack corrente per individuare questi valori." ? Puoi approfondire questo per favore?
    2015-05-03 09: 36: 25Z

Nel seguente codice C #

 
public void Method1()
{
    int i = 4;
    int y = 2;
    class1 cls1 = new class1();
}

Ecco come viene gestita la memoria

Immagine di variabili nello stack

Local Variables che ha bisogno solo di durare finché l'invocazione della funzione va in pila. L'heap viene utilizzato per le variabili la cui durata non è nota in anticipo, ma ci aspettiamo che durino un po '. Nella maggior parte delle lingue è fondamentale sapere al momento della compilazione quanto sia grande una variabile se vogliamo salvarla sullo stack.

Gli oggetti (che variano di dimensioni man mano che li aggiorniamo) vanno in pila perché non sappiamo al momento della creazione quanto tempo dureranno. In molti linguaggi, l'heap è garbage collection per trovare oggetti (come l'oggetto cls1) che non hanno più riferimenti.

In Java, la maggior parte degli oggetti va direttamente nell'heap. In linguaggi come C /C ++, le strutture e le classi possono spesso rimanere in pila quando non hai a che fare con i puntatori.

Ulteriori informazioni possono essere trovate qui:

La differenza tra stack e allocazione memoria heap «timmurphy.org

e qui:

Creazione di oggetti nello stack e heap

Questo articolo è la fonte dell'immagine sopra: Sei importanti concetti .NET: Stack, heap, tipi di valori, tipi di riferimento, boxing e unboxing - CodeProject

ma attenzione perché potrebbe contenere alcune imprecisioni.

    
388
2018-03-07 10: 27: 28Z
  1. Questo non è corretto. i e cls non sono variabili "statiche". sono chiamate variabili "locali" o "automatiche". È una distinzione molto importante. Vedi [link] stackoverflow.com/a/13326916/1763801 per chiarimenti
    2012-11-10 23: 05: 05Z
  2. Non ho detto che erano statiche variabili . Ho detto che int e cls1 sono statici elementi . La loro memoria è allocata staticamente e quindi vanno in pila. Questo è in contrasto con un oggetto che richiede l'allocazione dinamica della memoria, che quindi va in pila.
    2012-11-20 14: 38: 13Z
  3. Cito "Articoli statici ... vai in pila". Questo è semplicemente sbagliato. Gli elementi statici vanno nel segmento dati, gli elementi automatici vanno in pila.
    2012-11-21 16: 55: 41Z
  4. Anche chi ha scritto quell'articolo codeproject non sa wcappello di cui sta parlando. Ad esempio, dice "quelli primitivi hanno bisogno di memoria di tipo statico" che è completamente falso. Niente ti impedisce di allocare le primitive nell'heap in modo dinamico, basta scrivere qualcosa come "int array [] = new int [num]" e voilà, primitive allocate dinamicamente in .NET. Questa è solo una delle numerose inesattezze.
    2012-11-21 17: 02: 46Z
  5. Ho modificato il tuo post perché hai commesso gravi errori tecnici su ciò che entra nello stack e nell'heap.
    2014-09-09 23: 09: 12Z

Lo stack Quando si chiama una funzione, gli argomenti a tale funzione più qualche altro overhead vengono messi in pila. Alcune informazioni (come ad esempio dove andare al ritorno) sono anche memorizzate lì. Quando dichiari una variabile all'interno della tua funzione, quella variabile viene allocata nello stack.

La deallocazione dello stack è piuttosto semplice perché si rilascia deallocate sempre nell'ordine inverso in cui viene allocata. Le risorse di stack vengono aggiunte non appena si inseriscono le funzioni, i dati corrispondenti vengono rimossi man mano che si esce. Ciò significa che tendi a rimanere in una piccola area dello stack, a meno che non chiami molte funzioni che chiamano molte altre funzioni (o crei una soluzione ricorsiva).

The Heap L'heap è un nome generico per cui si inseriscono i dati che si creano al volo. Se non sai quante navicelle spaziali il tuo programma sta per creare, è probabile che tu usi l'operatore nuovo (o malloc o equivalente) per creare ciascuna astronave. Questa allocazione rimarrà per un po ', quindi è probabile che libereremo le cose in un ordine diverso da quello in cui le abbiamo create.

Quindi, l'heap è molto più complesso, perché finiscono per essere regioni di memoria che sono inutilizzate interlacciate con blocchi che sono - la memoria diventa frammentata. Trovare una memoria libera delle dimensioni necessarie è un problema difficile. Questo è il motivo per cui l'heap dovrebbe essere evitato (anche se è ancora spesso usato).

Implementazione L'implementazione sia dello stack che dell'heap è in genere ridotta al runtime /OS. Spesso i giochi e le altre applicazioni che sono critiche per le prestazioni creano le proprie soluzioni di memoria che catturano una grande quantità di memoria dall'heap e quindi li distribuiscono internamente per evitare di fare affidamento sul sistema operativo per la memoria.

Questo è pratico solo se l'utilizzo della memoria è molto diverso dalla norma, ad esempio per i giochi in cui carichi un livello in un'unica operazione e puoi buttare via tutto in un'altra enorme operazione.

Posizione fisica in memoria Questo è meno rilevante di quanto pensi a causa di una tecnologia chiamata Memoria virtuale che fa pensare al tuo programma che tu avere accesso ad un determinato indirizzo dove i dati fisici sono da qualche altra parte (anche sul disco fisso!). Gli indirizzi che ottieni per lo stack sono in ordine crescente man mano che l'albero delle chiamate diventa più profondo. Gli indirizzi per l'heap non sono prevedibili (vale a dire l'impianto specifico) e francamente non sono importanti.

    
197
2008-09-17 04: 34: 33Z
  1. Una raccomandazione per evitare di usare l'heap è abbastanza forte. I sistemi moderni hanno buoni gestori di heap e i moderni linguaggi dinamici utilizzano ampiamente l'heap (senza che il programmatore se ne preoccupi veramente). Direi di usare l'heap, ma con un allocatore manuale, non dimenticare di liberare!
    2008-09-17 04: 31: 42Z
  2. Se puoi usare lo stack o l'heap, usa lo stack. Se non puoi usare lo stack, davvero nessuna scelta. Uso sia molto, sia naturalmente usando std :: vector o hit simili nell'heap. Per un principiante, si evita l'heap perché lo stack è semplicemente così semplice !!
    2008-09-17 04: 35: 51Z
  3. Se la tua lingua non implementa la garbage collection, i puntatori intelligenti (oggetti allocati in modo specifico che avvolgono un puntatore che fa il conteggio dei riferimenti per i blocchi di memoria allocati dinamicamente) sono strettamente correlati Garbage Collection e sono un modo decente di gestire l'heap in modo sicuro e senza perdite. Sono implementati in vari framework, ma lo sonoanche non così difficile da implementare anche per i tuoi programmi.
    11-10-2016 19: 10: 40Z
  4. "Questo è il motivo per cui l'heap dovrebbe essere evitato (anche se è ancora spesso usato)." Non sono sicuro di cosa significhi in pratica, soprattutto perché la memoria viene gestita in modo diverso in molti linguaggi di alto livello. Dato che questa domanda è codificata come linguaggio indipendente, direi che questo particolare commento /linea è mal posizionato e non applicabile.
    2018-07-25 09: 34: 14Z
  5. Buon punto @JonnoHampson - Mentre fai un punto valido, direi che se stai lavorando in un "linguaggio di alto livello" con un GC probabilmente non lo fai Non preoccuparti dei meccanismi di allocazione della memoria - e quindi non ti interessa nemmeno cosa siano lo stack e l'heap.
    2018-07-26 22: 22: 52Z

Per chiarire, questa risposta ha informazioni errate ( thomas ha corretto la sua risposta dopo i commenti, figo :)). Altre risposte evitano semplicemente di spiegare cosa significa allocazione statica. Quindi spiegherò le tre principali forme di allocazione e in che modo si riferiscono in genere al mucchio, allo stack e al segmento di dati sottostante. Mostrerò anche alcuni esempi sia in C /C ++ che in Python per aiutare le persone a capire.

Le variabili "statiche" (AKA allocate staticamente) non sono allocate nello stack. Non dare per scontato - molte persone lo fanno solo perché "statico" suona molto come "stack". In realtà non esistono né nello stack né nell'heap. Fanno parte del cosiddetto segmento di dati .

Tuttavia, in genere è meglio considerare " scope " e " lifetime " anziché "stack" e "heap".

L'ambito si riferisce a quali parti del codice possono accedere a una variabile. In generale, pensiamo a ambito locale (accessibile solo dalla funzione corrente) rispetto a ambito globale (accessibile ovunque) anche se l'ambito può diventare molto più complesso.

La durata si riferisce a quando una variabile viene allocata e deallocata durante l'esecuzione del programma. Di solito pensiamo a allocazione statica (la variabile persisterà per l'intera durata del programma, rendendola utile per archiviare le stesse informazioni su più chiamate di funzione) rispetto a allocazione automatica (variabile persiste solo durante una singola chiamata a una funzione, rendendolo utile per la memorizzazione di informazioni che vengono utilizzate solo durante la funzione e possono essere eliminate una volta terminato) rispetto a allocazione dinamica (variabili la cui durata è definita in fase di esecuzione , invece del tempo di compilazione come statico o automatico).

Sebbene la maggior parte dei compilatori e degli interpreti implementino questo comportamento in modo simile in termini di utilizzo di stack, heap, ecc., un compilatore può talvolta interrompere queste convenzioni se lo desidera fino a quando il comportamento è corretto. Ad esempio, a causa dell'ottimizzazione, una variabile locale può esistere solo in un registro o essere rimossa completamente, anche se la maggior parte delle variabili locali esistono nello stack. Come è stato sottolineato in alcuni commenti, sei libero di implementare un compilatore che non usi nemmeno uno stack o un heap, ma piuttosto altri meccanismi di archiviazione (raramente fatti, dato che stack e heap sono grandi per questo). /p>

Fornirò del semplice codice C annotato per illustrare tutto questo. Il modo migliore per imparare è eseguire un programma con un debugger e osservare il comportamento. Se preferisci leggere python, vai alla fine della risposta:)

 
// 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 esempio particolarmente significativo del perché è importante distinguere tra durata e ambito è che una variabile può avere un ambito locale ma una durata statica, ad esempio "someLocalStaticVariable" nell'esempio di codice sopra riportato. Tali variabili possono rendere le nostre abitudini di denominazione comuni ma informali molto confuse. Ad esempio quando diciamo " local " di solito intendiamo " variabile allocata automaticamente localmente con scope " e quando diciamo globale intendiamo di solito " variabile allocata staticamente con scope globale ". Sfortunatamente, quando si tratta di cose come " variabili con scope statiche per il file " molte persone dicono semplicemente ... " huh ??? ".

Alcune delle scelte di sintassi in C /C ++ esacerbano questo problema - per esempio molte persone pensano che le variabili globali non siano "statiche" a causa della sintassi mostrata sotto.

 
int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation

int main() {return 0;}

Si noti che inserendo la parola chiave "statica" nella dichiarazione precedente impedisce a var2 di avere uno scope globale. Tuttavia, la var1 globale ha un'allocazione statica. Questo non è intuitivo! Per questo motivo, cerco di non utilizzare mai la parola "statico" quando descrivo l'ambito e dico invece qualcosa come "file" o "file limitato". Tuttavia, molte persone usano la frase "statico" o "ambito statico" per descrivere una variabile a cui è possibile accedere solo da un file di codice. Nel contesto della durata, "statico" sempre significa che la variabile viene allocata all'avvio del programma e deallocata quando termina il programma.

Alcune persone pensano a questi concetti come specifici per C /C ++. Non sono. Per esempio, l'esempio di Python qui sotto illustra tutti e tre i tipi di allocazione (ci sono alcune sottili differenze nelle lingue interpretate che non entrerò qui).

 
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
    
178
2017-07-30 12: 13: 36Z
  1. Vorrei fare riferimento a una variabile statica dichiarata all'interno di una funzione che ha solo accessibilità locali, ma generalmente non userebbe il termine "scope" con esso. Inoltre, può valere la pena notare che l'unico aspetto stack /heap con cui le lingue hanno essenzialmente zero flessibilità: un linguaggio che salva il contesto di esecuzione su uno stack non può usare quello stesso stack per contenere cose che dovranno sopravvivere ai contesti in cui sono create . Alcuni linguaggi come PostScript hanno stack multipli, ma hanno un "heap" che si comporta più come uno stack.
    2013-12-09 21: 53: 25Z
  2. @ supercat Tutto ciò ha senso. Ho definito l'ambito come "quali parti del codice possono accedere a una variabile" (e ritenere che questa sia la definizione più standard) quindi penso che siamo d'accordo:)
    2013-12-17 20: 28: 57Z
  3. Considererei lo "scope" di una variabile come limitata dal tempo e dallo spazio. Una variabile in ambito oggetto-oggetto è necessaria per mantenere il suo valore finché esiste l'oggetto. È necessaria una variabile all'interno di un ambito del contesto di esecuzione per mantenere il suo valore fintanto che l'esecuzione rimane in tale contesto. Una dichiarazione di variabili statiche crea un identificatore il cui ambito è limitato al blocco corrente, che è collegato a una variabile il cui ambito è illimitato.
    2013-12-17 20: 57: 52Z
  4. @ supercat Ecco perché uso la parola lifetime, che è il modo in cui definisco ciò che chiami scope time. Riduce la necessità di sovraccaricare la parola "scope" con così tanti significati. Per quanto posso dire, non sembra esserci un consenso totale sulle definizioni esatte, anche se tra le fonti canoniche. La mia terminologia è disegnata parzialmente da K & R e parzialmente dall'uso prevalente nel primo dipartimento CS che ho studiato /insegnato. Sempre bene ascoltare un'altra vista informata.
    2013-12-28 22: 50: 47Z
  5. stai scherzando. puoi veramente definire una variabile statica all'interno di una funzione?
    2017-05-16 09: 57: 26Z

Altri hanno risposto abbastanza bene alle ampie righe, quindi aggiungerò alcuni dettagli.

  1. Lo stack e l'heap non devono essere singolari. Una situazione comune in cui si dispone di più di uno stack è se si dispone di più thread in un processo. In questo caso ogni thread ha il proprio stack. È anche possibile avere più di un heap, ad esempio alcune configurazioni DLL possono comportare l'allocazione di DLL diverse da diversi heap, motivo per cui è generalmente una cattiva idea rilasciare la memoria allocata da una libreria diversa.

  2. In C puoi ottenere il beneficio dell'allocazione della lunghezza variabile attraverso l'uso di alloca , che alloca sullo stack, anziché allocare, che alloca sull'heap. Questa memoria non sopravviverà alla tua dichiarazione di ritorno, ma è utile per un buffer di scratch.

  3. Creare un buffer temporaneo enorme su Windows che non usi molto non è gratuito. Questo perché il compilatore genererà un loop probe di stack che viene chiamato ogni volta che viene inserita la funzione per assicurarsi che lo stack esista (perché WinDows utilizza una singola pagina di guardia alla fine del tuo stack per rilevare quando ha bisogno di aumentare lo stack. Se accedi alla memoria più di una pagina dalla fine dello stack, si bloccherà). Esempio:

 
void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}
    
161
2017-07-30 11: 18: 35Z
  1. Re "al contrario di allocare": intendi "al contrario di malloc"?
    2017-07-30 11: 19: 36Z
  2. Quanto è portatile alloca?
    2017-07-30 11: 20: 14Z
  3. @ PeterMortensen non è POSIX, portabilità non garantita.
    2017-11-01 17: 38: 27Z

Altri hanno risposto direttamente alla tua domanda, ma quando provo a capire lo stack e l'heap, penso che sia utile considerare il layout di memoria di un processo UNIX tradizionale (senza thread e allocatori basati su mmap()). La Glossario di gestione della memoria ha uno schema di questo layout di memoria.

Lo stack e l'heap si trovano tradizionalmente alle estremità opposte dello spazio degli indirizzi virtuali del processo. Lo stack cresce automaticamente quando vi si accede, fino a una dimensione impostata dal kernel (che può essere regolata con setrlimit(RLIMIT_STACK, ...)). L'heap aumenta quando l'allocatore di memoria richiama la chiamata di sistema brk() o sbrk(), mappando più pagine di memoria fisica nello spazio degli indirizzi virtuali del processo.

Nei sistemi senza memoria virtuale, come ad esempio alcuni sistemi embedded, spesso si applica lo stesso layout di base, tranne che lo stack e l'heap sono di dimensioni fisse. Tuttavia, in altri sistemi embedded (come quelli basati su microcontrollori PIC Microchip), lo stack del programma è un blocco di memoria separato che non è indirizzabile dalle istruzioni di spostamento dei dati e può essere modificato o letto solo indirettamente tramite le istruzioni del flusso del programma (chiamata, ritorno, ecc.). Altre architetture, come i processori Intel Itanium, hanno stack multipli . In questo senso, lo stack è un elemento dell'architettura della CPU.

    
128
2015-08-05 20: 36: 31Z

Lo stack è una porzione di memoria che può essere manipolata tramite diverse istruzioni del linguaggio assembly chiave, come 'pop' (rimuovere e restituire un valore dallo stack) e 'push' (spingere un valore nello stack), ma chiama anche (chiama una subroutine - questo spinge l'indirizzo per tornare allo stack) e ritorna (ritorna da una subroutine - questo fa uscire l'indirizzo dallo stack e lo salta). È la regione della memoria sotto il registro del puntatore dello stack, che può essere impostato secondo necessità. Lo stack viene anche utilizzato per passare argomenti alle subroutine e anche per preservare i valori nei registri prima di chiamare le subroutine.

L'heap è una porzione di memoria che viene fornita a un'applicazione dal sistema operativo, in genere attraverso un syscall come malloc. Sui SO moderni questa memoria è un insieme di pagine a cui solo il processo chiamante ha accesso.

La dimensione dello stack è determinata in fase di esecuzione e generalmente non aumenta dopo l'avvio del programma. In un programma in C, lo stack deve essere abbastanza grande da contenere ogni variabile dichiarata all'interno di ogni funzione. L'heap crescerà dinamicamente secondo le necessità, ma il sistema operativo sta alla fine effettuando la chiamata (spesso farà crescere l'heap di oltre il valore richiesto da malloc, così che almeno alcuni mallocs futuri non avranno bisogno di tornare al kernel per ottieni più memoria. Questo comportamento è spesso personalizzabile)

Dato che hai allocato lo stack prima di avviare il programma, non hai mai bisogno di malloc prima di poter usare lo stack, quindi è un piccolo vantaggio lì. In pratica, è molto difficile prevedere cosa sarà veloce e cosa sarà lento nei moderni sistemi operativi che hanno sottosistemi di memoria virtuale, perché il modo in cui le pagine sono implementate e dove sono memorizzate è un dettaglio di implementazione.

    
109
2008-09-17 04: 29: 20Z
  1. Vale anche la pena ricordare che Intel ottimizza pesantemente gli accessi allo stack, specialmente cose come prevedere dove si torna da una funzione.
    2008-09-17 04: 37: 38Z

Penso che molte altre persone ti abbiano dato risposte per lo più corrette su questo argomento.

Un dettaglio che è stato mancato, tuttavia, è che "l'heap" dovrebbe essere chiamato "free store". La ragione di questa distinzione è che l'archivio gratuito originale è stato implementato con una struttura dati nota come "heap binomiale". Per questo motivo, l'allocazione dalle prime implementazioni di malloc () /free () era l'allocazione da un heap. Tuttavia, in questo giorno moderno, la maggior parte dei negozi gratuiti sono implementati con strutture dati molto elaborate che non sono cumuli binomiali.

    
109
2008-09-17 04: 57: 51Z
  1. Un altro nitpick- la maggior parte delle risposte (leggermente) implicano che l'uso di uno "stack" è richiesto dalla lingua C. Questo è un malinteso comune, sebbene sia il paradigma (di gran lunga) dominante per l'implementazione di C99 6.2.4 automatic storage duration objects (variabili). Infatti, la parola "stack" non appare nemmeno nello standard di linguaggio C99: open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
    2009-09-01 05: 03: 55Z
  2. [@ Heath] Ho un piccolo commento sulla tua risposta. Dai un'occhiata alla risposta accettata a questa domanda . Dice che lo store gratuito molto probabilmente è lo stesso del heap , anche se non necessariamente.
    2012-02-12 06: 34: 39Z

Che cos'è uno stack?

Una pila è una pila di oggetti, di solito una ben organizzata.

 Inserisci la descrizione dell'immagine qui

  
    

Le pile nelle architetture di calcolo sono regioni di memoria in cui i dati vengono aggiunti o rimossi in un modo ultimo-a-prima-out.
    In un'applicazione multi-thread, ogni thread avrà il proprio stack.

  

Che cos'è un heap?

Un mucchio è una disordinata raccolta di cose accumulate casualmente.

 Inserisci la descrizione dell'immagine qui

  
    

Nelle architetture di calcolo l'heap è un'area di memoria allocata dinamicamente che viene gestita automaticamente dal sistema operativo o dalla libreria del gestore di memoria.
    La memoria nell'heap viene allocata, deallocata e ridimensionata regolarmente durante l'esecuzione del programma e questo può portare a un problema chiamato frammentazione.
    La frammentazione si verifica quando gli oggetti di memoria sono allocati con piccoli spazi intermedi troppo piccoli per contenere oggetti di memoria aggiuntivi.
    Il risultato netto è una percentuale dello spazio dell'heap che non è utilizzabile per ulteriori allocazioni di memoria.

  

Entrambi insieme

  
    

In un'applicazione multi-thread, ogni thread avrà il suo stack. Ma tutti i diversi thread condivideranno l'heap.
    Poiché i diversi thread condividono l'heap in un'applicazione multi-thread, ciò significa anche che deve esserci un po 'di coordinamento tra i thread in modo che non provino ad accedere e manipolare lo stesso pezzo (i) di memoria nell'heap allo stesso tempo.

  

Qual è più veloce: lo stack o l'heap? E perché?

  
    

Lo stack è molto più veloce dell'heap.
    Questo è a causa del modo in cui tla memoria del cappello è allocata sullo stack.
    L'allocazione della memoria nello stack è semplice come spostare il puntatore dello stack verso l'alto.

  

Per le persone nuove alla programmazione, è probabilmente una buona idea usare lo stack dal momento che è più semplice.
Poiché lo stack è di piccole dimensioni, è consigliabile utilizzarlo quando si conosce esattamente la quantità di memoria necessaria per i dati o se si conosce che la dimensione dei dati è molto ridotta.
È meglio usare l'heap quando sai che avrai bisogno di molta memoria per i tuoi dati, o semplicemente non sei sicuro di quanta memoria hai bisogno (come con un array dinamico).

Modello di memoria Java

 Inserisci la descrizione dell'immagine qui

Lo stack è l'area della memoria in cui sono memorizzate le variabili locali (compresi i parametri del metodo). Quando si tratta di variabili oggetto, questi sono semplicemente riferimenti (puntatori) agli oggetti reali nell'heap.
Ogni volta che un oggetto viene istanziato, un blocco di memoria heap viene messo da parte per contenere i dati (stato) di quell'oggetto. Poiché gli oggetti possono contenere altri oggetti, alcuni di questi dati possono infatti contenere riferimenti a tali oggetti nidificati.

    
105
2017-07-30 12: 16: 46Z

Puoi fare cose interessanti con lo stack. Ad esempio, hai funzioni come alloca (presumendo che tu possa superare gli avvertimenti copiosi relativi al suo use), che è una forma di malloc che utilizza specificamente lo stack, non l'heap, per la memoria.

Detto questo, gli errori di memoria basati sullo stack sono tra i peggiori che abbia mai visto. Se si utilizza la memoria heap e si superano i limiti del blocco assegnato, si ha una buona possibilità di attivare un errore di segmento. (Non 100%: il tuo blocco potrebbe essere incidentalmente contiguo con un altro che hai precedentemente assegnato.) Ma poiché le variabili create nello stack sono sempre contigue tra loro, la scrittura fuori limite può cambiare il valore di un'altra variabile. Ho imparato che ogni volta che sento che il mio programma ha smesso di obbedire alle leggi della logica, probabilmente è un buffer overflow.

    
87
2009-03-19 15: 55: 06Z
  1. Quanto è portatile alloca? Ad esempio, funziona su Windows? È solo per sistemi operativi di tipo Unix?
    2017-07-30 12: 00: 54Z

Semplicemente, lo stack è dove vengono create le variabili locali. Inoltre, ogni volta che si chiama una subroutine, il contatore del programma (puntatore all'istruzione della macchina successiva) e qualsiasi registro importante, e talvolta i parametri vengono messi in pila. Quindi qualsiasi variabile locale all'interno della subroutine viene inserita nello stack (e utilizzata da lì). Quando finisce la subroutine, tutte le cose vengono rimosse dallo stack. Il PC e i dati del registro si rimettono e rimettono dove erano così come sono spuntati, così il tuo programma può andare avanti alla grande.

L'heap è l'area in cui sono allocate le allocazioni di memoria dinamica (chiamate esplicite "nuove" o "allocate"). È una struttura dati speciale in grado di tenere traccia dei blocchi di memoria di varie dimensioni e del loro stato di assegnazione.

Nei sistemi "classici", la RAM era strutturata in modo tale che il puntatore dello stack iniziava nella parte inferiore della memoria, il puntatore dell'heap si avviava in alto e cresceva uno verso l'altro. Se si sovrappongono, sei fuori RAM. Tuttavia, ciò non funziona con i moderni sistemi operativi multi-thread. Ogni thread deve avere il proprio stack e quelli possono essere creati dinamicamente.

    
85
2009-03-19 15: 19: 30Z
  1. [@ T.E.D.] Perché hai detto "a volte i parametri vengono messi in pila"? Quello che so è che loro sono sempre . Potresti per favore elaborare di più?
    2012-02-12 06: 36: 42Z
  2. @ OmarOthman - Dico questo perché spetta interamente allo scrittore del tuo compilatore /interprete cosa succede quando viene chiamata una subroutine. Il classico comportamento di Fortran è di non utilizzare affatto una pila. Alcune lingue supportano cose esotiche come il pass-by-name, che in realtà è una sostituzione testuale.
    2012-04-03 15: 57: 07Z

Da WikiAnwser.

Stack

Quando una funzione o un metodo chiama un'altra funzione che a sua volta chiama un'altra funzione, ecc., l'esecuzione di tutte quelle funzioni rimane sospesa finché l'ultima funzione non restituisce il suo valore.

Questa catena di chiamate a funzioni sospese è lo stack, perché gli elementi nello stack (chiamate di funzione) dipendono l'uno dall'altro.

Lo stack è importante da considerare nella gestione delle eccezioni e nelle esecuzioni dei thread.

Heap

L'heap è semplicemente la memoria utilizzata dai programmi per memorizzare le variabili. Gli elementi dell'heap (variabili) non hanno dipendenze tra loro e possono sempre essere consultati casualmente in ogni momento.

    
79
2017-07-30 12: 01: 46Z
  1. "Mi piace la risposta accettata meglio poiché è ancora più basso livello." Questa è una brutta cosa, non una buona cosa.
    2017-04-25 09: 02: 17Z

Stack

  • Accesso molto veloce
  • Non devi deselezionare esplicitamente le variabili
  • Lo spazio è gestito in modo efficiente dalla CPU, la memoria non sarà frammentata ​​li>
  • Solo variabili locali
  • Limite sulla dimensione dello stack (dipendente dal sistema operativo)
  • Le variabili non possono essere ridimensionate

Heap

  • Le variabili sono accessibili globalmente
  • Nessun limite per le dimensioni della memoria
  • (Relativamente) più lento accesso
  • Nessun utilizzo efficiente garantito dello spazio, la memoria potrebbe frammentarsi nel tempo quando vengono allocati blocchi di memoria, quindi liberati
  • Devi gestire la memoria (sei incaricato di allocare e liberare le variabili)
  • Le variabili possono essere ridimensionate usando realloc ()
50
2017-07-30 12: 14: 32Z

OK, semplicemente e in poche parole, significano ordinati e non ordinati ...!

Stack : negli elementi dello stack, le cose si ottengono l'una sopra l'altra, significa che sarà più veloce ed efficiente da elaborare! ...

Quindi c'è sempre un indice per puntare l'elemento specifico, anche l'elaborazione sarà più veloce, c'è anche una relazione tra gli oggetti! ...

Heap : nessun ordine, l'elaborazione sarà più lenta e i valori vengono incasinati insieme senza un ordine o indice specifico ... ci sono casi casuali e non vi è alcuna relazione tra loro ... quindi esecuzione e il tempo di utilizzo potrebbe variare ...

Creo anche l'immagine qui sotto per mostrare come possono apparire:

 inserisci la descrizione dell'immagine qui

    
42
2018-04-23 02: 06: 25Z

In breve

Uno stack viene utilizzato per l'allocazione della memoria statica e un heap per l'allocazione dinamica della memoria, entrambi memorizzati nella RAM del computer.


In dettaglio

Lo stack

Lo stack è una struttura di dati "LIFO" (last in, first out), che è gestita e ottimizzata dalla CPU abbastanza da vicino. Ogni volta che una funzione dichiara una nuova variabile, viene "spinta" nello stack. Quindi ogni volta che una funzione termina, tutte le variabili inserite nello stack da quella funzione, vengono liberate (vale a dire, vengono eliminate). Una volta liberata una variabile stack, quella regione di memoria diventa disponibile per un'altra variabile stacks.

Il vantaggio di utilizzare lo stack per memorizzare le variabili è che la memoria è gestita per te. Non è necessario allocare memoria a mano o liberarla quando non ne hai più bisogno. Inoltre, poiché la CPU organizza la memoria dello stack in modo efficiente, la lettura e la scrittura nello stack delle variabili sono molto veloci.

Altro può essere trovato qui .


The Heap

L'heap è un'area della memoria del computer che non è gestita automaticamente per te e non è gestita così strettamente dalla CPU. È una regione di memoria più fluttuante (ed è più grande). Per allocare memoria sull'heap, è necessario utilizzare malloc () o calloc (), che sono funzioni C incorporate. Una volta allocata memoria nell'heap, sei responsabile dell'uso gratuito () per deallocare quella memoria quando non ne hai più bisogno.

Se non si riesce a farlo, il programma avrà quella che è nota come perdita di memoria. Cioè, la memoria sull'heap sarà ancora messa da parte (e non sarà disponibile per altri processi). Come vedremo nella sezione di debug, c'è uno strumento chiamato Valgrind che può aiutarti a rilevare la memoria perdite.

A differenza dello stack, l'heap non ha restrizioni di dimensioni su dimensioni variabili (a parte le ovvie limitazioni fisiche del computer). La memoria heap è leggermente più lenta da leggere e scrivere, perché è necessario utilizzare i puntatori per accedere alla memoria nell'heap. Ne parleremo a breve.

Diversamente dallo stack, le variabili create nell'heap sono accessibili da qualsiasi funzione, in qualsiasi punto del programma. Le variabili heap sono di portata globale.

Altro può essere trovato qui .


Le variabili allocate nello stack sono memorizzate direttamente nella memoria e l'accesso a questa memoria è molto veloce e la sua allocazione viene gestita al momento della compilazione del programma. Quando una funzione o un metodo chiama un'altra funzione che a sua volta chiama un'altra funzione, ecc., L'esecuzione di tutte quelle funzioni rimane sospesa finché l'ultima funzione non restituisce il suo valore. Lo stack è sempre riservato in un ordine LIFO, il blocco riservato più recentemente è sempre il blocco successivo da liberare. Questo rende molto semplice tenere traccia dello stack, liberare un blocco dallo stack non è altro che regolare un puntatore.

Le variabili allocate nell'heap hanno la memoria allocata in fase di esecuzione e l'accesso a questa memoria è un po 'più lento, ma la dimensione dell'heap è limitata solo dalla dimensione della memoria virtuale. Gli elementi dell'heap non hanno dipendenze tra loro e possono sempre essere consultati casualmente in qualsiasi momento. È possibile allocare un blocco in qualsiasi momento e liberarlo in qualsiasi momento. Ciò rende molto più complesso tenere traccia di quali parti dell'heap sono allocate o libere in un dato momento.

 Inserisci la descrizione dell'immagine qui

Puoi usare lo stack se sai esattamente quanti dati hai bisogno di allocare prima della compilazione, e non è troppo grande. Puoi utilizzare l'heap se non sai esattamente quanti dati hai bisogno in fase di esecuzione o se hai bisogno di allocare molti dati.

In una situazione multi-threading ogni thread avrà il proprio stack completamente indipendente, ma condivideranno l'heap. Lo stack è specifico del thread e l'heap è specifico dell'applicazione. Lo stack è importante da considerare nella gestione delle eccezioni e nelle esecuzioni dei thread.

Ogni thread riceve uno stack, mentre in genere c'è solo un heap per l'applicazione (sebbene non sia raro avere più heap per diversi tipi di allocazione).

 Inserisci la descrizione dell'immagine qui

Al momento dell'esecuzione, se l'applicazione ha bisogno di più heap, può allocare memoria dalla memoria libera e se lo stack ha bisogno di memoria, può allocare memoria dalla memoria libera allocata per l'applicazione.

Anche, maggiori dettagli sono forniti qui e qui .


Ora vai a le risposte alle tue domande .

  

In che misura sono controllati dal sistema operativo o dal runtime della lingua?

Il sistema operativo alloca lo stack per ogni thread a livello di sistema quando viene creato il thread. In genere il sistema operativo viene chiamato dal runtime della lingua per allocare l'heap per l'applicazione.

Altro può essere found qui .

  

Qual è il loro ambito di applicazione?

Già indicato in alto.

  

"Puoi usare lo stack se sai esattamente quanti dati hai bisogno di allocare prima della compilazione, e non è troppo grande. Puoi usare l'heap se non sai esattamente di quanti dati avrai bisogno a runtime o se è necessario allocare molti dati. "

Altro può essere trovato in qui .

  

Che cosa determina la dimensione di ciascuno di essi?

La dimensione della pila è impostata da OS quando viene creato un thread. La dimensione dell'heap è impostata all'avvio dell'applicazione, ma può aumentare man mano che lo spazio è necessario (l'allocatore richiede più memoria dal sistema operativo).

  

Cosa rende più veloce?

L'allocazione dello stack è molto più veloce poiché tutto ciò che fa realmente è spostare il puntatore dello stack. Usando i pool di memoria, è possibile ottenere prestazioni comparabili dall'allocazione dell'heap, ma ciò comporta una leggera complessità aggiuntiva e il suo mal di testa.

Inoltre, stack vs. heap non è solo una considerazione prestazionale; ti dice anche molto sulla vita attesa degli oggetti.

I dettagli possono essere trovati da qui .

    
40
2018-12-09 15: 12: 15Z

Negli anni '80, UNIX si è propagato come coniglietti con le grandi compagnie che si muovevano da sole. Exxon ne aveva uno così come decine di nomi di marchi persi nella storia. La disposizione della memoria era a discrezione dei molti implementatori.

Un tipico programma in C è stato disposto in memoria con un'opportunità per aumentare cambiando il valore di brk (). In genere, l'HEAP era appena al di sotto di questo valore di valore e l'aumento di BR ha aumentato la quantità di heap disponibile.

Il singolo STACK era tipicamente un'area sotto HEAP che era un tratto di memoria contenente nulla di valore fino alla cima del prossimo blocco fisso di memoria. Questo blocco successivo era spesso CODICE che poteva essere sovrascritto dai dati dello stack in uno dei famosi hack della sua era.

Un tipico blocco di memoria era BSS (un blocco di valori zero) che è stato accidentalmente non azzerato nell'offerta di un produttore. Un altro era DATA contenente valori inizializzati, comprese stringhe e numeri. Un terzo era CODICE contenente CRT (runtime C), main, funzioni e librerie.

L'avvento della memoria virtuale in UNIX modifica molti dei vincoli. Non vi è alcuna ragione obiettiva per cui questi blocchi debbano essere contigui, o fissato in dimensioni, o ordinato un modo particolare ora. Ovviamente, prima che UNIX fosse Multics non soffriva di questi vincoli. Ecco uno schema che mostra uno dei layout di memoria di quell'era.

Un tipico layout di memoria del programma UNIX C in stile anni '80

    
35
2015-03-27 19: 55: 51Z

stack , heap e dati di ogni processo nella memoria virtuale:

 stack, heap e dati statici

    
29
2018-03-12 18: 00: 15Z

Un paio di centesimi: penso che sarà bene disegnare la memoria grafica e più semplice:

 Questa è la mia visione della costruzione della memoria di processo con la semplificazione per una comprensione più semplice che sta accadendo


Frecce: mostra dove cresce stack e heap, le dimensioni dello stack del processo hanno un limite definito nel sistema operativo, i limiti delle dimensioni dello stack di threaddi parametri in thread creare API di solito. Heap di solito limita la dimensione massima della memoria virtuale del processo, ad esempio per 32 bit 2-4 GB.

Così semplice: l'heap del processo è generale per il processo e tutti i thread all'interno, utilizzando per allocazione di memoria nel caso comune con qualcosa come malloc () .

Lo stack è una memoria rapida per l'archiviazione in indicatori di ritorno e variabili della funzione di caso comune, elaborati come parametri nella chiamata di funzione, variabili di funzione locali.

    
24
2017-07-30 12: 22: 02Z

Dal momento che alcune risposte sono state pignoli, ho intenzione di contribuire con il mio acaro.

Sorprendentemente, nessuno ha menzionato questo multiplo (cioè non correlato al numero di thread a livello OS in esecuzione) che gli stack di chiamata devono essere trovati non solo in lingue esotiche (PostScript) o piattaforme (Intel Itanium), ma anche in fibre , thread verdi e alcune implementazioni di coroutine .

Fibre, fili verdi e coroutine sono per molti aspetti simili, il che porta a molta confusione. La differenza tra fibre e fili verdi è che i primi usano il multitasking cooperativo, mentre i secondi possono essere sia cooperativi che preventivi (o anche entrambi). Per la distinzione tra fibre e coroutine, vedi qui .

In ogni caso, lo scopo di entrambe le fibre, i thread verdi e le coroutine è eseguire simultaneamente più funzioni, ma non in parallelo (vedi questa domanda SO per la distinzione) all'interno di una singola discussione a livello di sistema operativo, trasferendo il controllo avanti e indietro gli uni dagli altri in modo organizzato .

Quando usi fibre, fili verdi o coroutine, di solito hai uno stack separato per funzione. (Tecnicamente, non solo una pila, ma un intero contesto di esecuzione è per funzione.Ma soprattutto, registri della CPU.) Per ogni thread ci sono tanti stack quante sono le funzioni in esecuzione contemporaneamente, e il thread passa tra l'esecuzione di ogni funzione secondo la logica del tuo programma. Quando una funzione è in esecuzione, la sua pila viene distrutta. Quindi, il numero e le durate degli stack sono dinamici e non sono determinati dal numero di thread a livello di sistema operativo!

Nota che ho detto " di solito avere uno stack separato per funzione". Ci sono entrambe le implementazioni stackful e stackless delle couroutines. Le implementazioni C ++ più importanti e imprevedibili sono Boost.Coroutine e Microsoft PPL 's async/await. (Tuttavia, le funzioni di ripristino di C ++ (aka "async e await"), che sono stati proposti in C ++ 17, è probabile che utilizzino coroutine senza stack.)

La proposta di fibre alla libreria standard C ++ è imminente. Inoltre, ci sono alcune librerie di terze parti. I thread verdi sono estremamente popolari in linguaggi come Python e Ruby.

    
21
2017-05-23 11: 55: 01Z

Ho qualcosa da condividere, anche se i punti principali sono già trattati.

Stack

  • Accesso molto veloce.
  • Memorizzato nella RAM.
  • Le chiamate di funzione vengono caricate qui insieme alle variabili locali e ai parametri di funzione passati.
  • Lo spazio viene liberato automaticamente quando il programma esce da un ambito.
  • Memorizzato nella memoria sequenziale.

Heap

  • Accesso lento in confronto allo Stack.
  • Memorizzato nella RAM.
  • Le variabili create dinamicamente sono memorizzate qui, che in seguito richiede la liberazione della memoria allocata dopo l'uso.
  • Memorizzato ovunque venga effettuata l'allocazione della memoria, accessibile sempre tramite puntatore.

Nota interessante:

  • Se le chiamate alla funzione fossero state memorizzate in heap, si sarebbero ottenuti 2 punti disordinati:
    1. A causa della memorizzazione sequenziale nello stack, l'esecuzione è più veloce. L'archiviazione nell'heap avrebbe comportato un enorme consumo di tempo, rendendo l'intero programma più lento.
    2. Se le funzioni fossero memorizzate nell'heap (memoria disordinata puntata da un puntatore), non sarebbe stato possibile tornare al richiamo dell'indirizzo del chiamante (quale stack dà a causa dell'archiviazione sequenziale in memoria).
14
2018-12-10 08: 23: 58Z
  1. conciso e pulito. bello:)
    2018-12-05 19: 14: 07Z

Molte risposte sono corrette come concetti, ma dobbiamo notare che uno stack è necessario per l'hardware (cioè il microprocessore) per consentire la chiamata di subroutine (CALL in linguaggio assembly ...). (I ragazzi OOP lo chiameranno metodi )

Sulla pila si salvano gli indirizzi di ritorno e la chiamata → push /ret → pop viene gestita direttamente nell'hardware.

Puoi usare lo stack per passare i parametri .. anche se è più lento dell'uso dei registri (un guru del microprocessore direbbe o un buon libro del BIOS degli anni '80 ...)

  • Senza stack nessun microprocessore può funzionare. (non possiamo immaginare un programma, anche in linguaggio assembly, senza subroutine /funzioni)
  • Senza l'heap possibile. (Un programma di linguaggio assembly può funzionare senza, poiché l'heap è un concetto di sistema operativo, come malloc, ovvero una chiamata OS /Lib.

L'utilizzo dello stack è più veloce come:

  • L'hardware e persino il push /pop sono molto efficienti.
  • malloc richiede l'accesso alla modalità kernel, usa lock /semaphore (o altre primitive di sincronizzazione) eseguendo del codice e gestendo alcune strutture necessarie per tenere traccia dell'allocazione.
8
2017-08-07 08: 27: 43Z
  1. Che cos'è OPP? Intendi OOP ( object-oriented_programming )?
    2017-07-30 12: 34: 40Z
  2. Intendi dire che malloc è una chiamata al kernel?
    2017-07-30 12: 35: 56Z
  3. 1) sì, mi dispiace .. OOP ... 2) malloc: scrivo a breve, scusa ... malloc è nello spazio utente .. ma può innescare altri chiama .... il punto è che l'uso dell'heap può essere molto lento ...
    2017-08-03 12: 18: 19Z

Wow! Così tante risposte e non penso che una di esse abbia ragione ...

1) Dove e cosa sono (fisicamente nella memoria di un vero computer)?

Lo stack è la memoria che inizia come l'indirizzo di memoria più alto assegnato all'immagine del programma e quindi diminuisce di valore da lì. È riservato per i parametri di funzione chiamati e per tutte le variabili temporanee utilizzate nelle funzioni.

Ci sono due heap: pubblico e privato.

L'heap privato inizia su un limite di 16 byte (per programmi a 64 bit) o ​​su un limite di 8 byte (per programmi a 32 bit) dopo l'ultimo byte di codice nel programma, quindi aumenta di valore da lì . Viene anche chiamato heap predefinito.

Se l'heap privato diventa troppo grande si sovrapporrà all'area dello stack, così come lo stack si sovrappone all'heap se diventa troppo grande. Poiché lo stack inizia da un indirizzo più alto e scende fino a un indirizzo inferiore, con l'hacking corretto è possibile ottenere uno stack così grande da sovrascrivere l'area heap privata e sovrapporre l'area del codice. Il trucco è quindi quello di sovrapporre un numero sufficiente di aree del codice che è possibile collegare al codice. È un po 'complicato da fare e rischi un crash del programma, ma è facile e molto efficace.

L'heap pubblico risiede nel proprio spazio di memoria al di fuori dello spazio immagine del programma. È questomemoria che verrà sottratta sul disco rigido se le risorse di memoria scarseggiano.

2) In che misura sono controllati dal sistema operativo o dal runtime della lingua?

Lo stack è controllato dal programmatore, l'heap privato è gestito dal sistema operativo e l'heap pubblico non è controllato da nessuno in quanto si tratta di un servizio OS: si effettuano richieste e vengono concesse o negate.

2b) Qual è il loro scopo?

Sono tutti globali per il programma, ma i loro contenuti possono essere privati, pubblici o globali.

2c) Che cosa determina la dimensione di ciascuno di essi?

Le dimensioni dello stack e dell'heap privato sono determinate dalle opzioni di runtime del compilatore. L'heap pubblico viene inizializzato in fase di esecuzione utilizzando un parametro size.

2d) Cosa rende più veloce?

Non sono progettati per essere veloci, sono progettati per essere utili. Il modo in cui il programmatore li utilizza determina se sono "veloci" o "lenti"

REF:

https://norasandler.com/2019/02/18 /Write-a-compilatore-10.html

https://docs.microsoft. com /it-it /windows /desktop /api /heapapi /NF-heapapi-GetProcessHeap

https://docs.microsoft. com /it-it /windows /desktop /api /heapapi /NF-heapapi-HeapCreate

    
8
2019-02-20 02: 04: 38Z
fonte posta Qui
Altre domande