Perché i libri .Net parlano di allocazione della memoria stack vs heap?

36

Sembra che ogni libro .net parli di tipi di valore vs tipi di riferimento e lo renda un punto in cui spesso (in modo errato) viene indicato dove è archiviato ogni tipo - l'heap o lo stack. Di solito è nei primi capitoli e presentato come un fatto importantissimo. Penso che sia addirittura coperto dagli esami di certificazione . Perché stack vs heap contano anche per gli sviluppatori. (Principianti) .Net? Assegni cose e funziona, giusto?

    
posta Greg 03.11.2010 - 18:50
fonte

8 risposte

37

Mi sto convincendo che la ragione principale per cui questo bit di informazione è considerato importante è tradizione . Negli ambienti non gestiti, la distinzione tra stack e heap è importante e dobbiamo allocare ed eliminare manualmente il memoria che usiamo. Ora, la garbage collection si prende cura della gestione, quindi ignorano quel bit. Non penso che il messaggio abbia davvero capito che non dobbiamo preoccuparci di quale tipo di memoria sia usata.

Come ha sottolineato Fede, Eric Lippert ha alcune cose molto interessanti da dire su questo: link .

Alla luce di queste informazioni, è possibile modificare il mio primo paragrafo in modo da leggere sostanzialmente: "La ragione per cui le persone includono queste informazioni e presuppone che sia importante è a causa di informazioni errate o incomplete combinate con la necessità di questa conoscenza in passato."

Per coloro che pensano che sia ancora importante per motivi di prestazioni: quali azioni intraprenderei per spostare qualcosa dall'heap allo stack se hai misurato le cose e scoperto che importa? Più probabilmente, troverai un modo completamente diverso di migliorare le prestazioni dell'area problematica.

    
risposta data 03.11.2010 - 19:09
fonte
36

It seems like every .NET book talks about value types vs reference types and makes it a point to (often incorrectly) state where each type is stored - the heap or the stack. Usually it's in the first few chapters and presented as some all-important fact.

Sono completamente d'accordo; Lo vedo sempre.

Why do .NET books talk about stack vs heap memory allocation?

Una parte del motivo è dovuta al fatto che molte persone sono venute in C # (o in altri linguaggi .NET) da uno sfondo C o C ++. Poiché tali lingue non impongono le regole sulla durata dello storage, è necessario conoscere tali regole e implementare con attenzione il programma per seguirle.

Ora, conoscendo queste regole e seguendole in C, non richiede di capire "l'heap" e "lo stack". Ma se capisci come funzionano le strutture dati, spesso è più facile capire e seguire le regole.

Quando scrivi un libro per principianti è naturale che un autore spieghi i concetti nello stesso ordine in cui loro li hanno appresi. Questo non è necessariamente l'ordine che ha senso per l'utente. Recentemente sono stato redattore tecnico del libro per principianti del C # 4 di Scott Dorman, e una delle cose che mi è piaciuta è che Scott ha scelto un ordine piuttosto ragionevole per gli argomenti, piuttosto che iniziare su argomenti realmente avanzati nella gestione della memoria. / p>

Un'altra parte del motivo è che alcune pagine della documentazione MSDN sottolineano con forza le considerazioni sull'archiviazione. Documentazione MSDN particolarmente vecchia che è ancora in agguato fin dai primi giorni. Gran parte di quella documentazione ha errori sottili che non sono mai stati escissi, e devi ricordare che è stato scritto in un momento particolare della storia e per un particolare pubblico.

Why does stack vs heap even matter to (beginner) .NET developers?

Secondo me, non è così. Ciò che è molto più importante da capire è roba del tipo:

  • Qual è la differenza nella semantica della copia tra un tipo di riferimento e un tipo di valore?
  • Come si comporta un parametro "ref int x"?
  • Perché i tipi di valore dovrebbero essere immutabili?

E così via.

You allocate stuff and it just works, right?

È l'ideale.

Ora ci sono situazioni in cui è importante. La raccolta dei rifiuti è eccezionale e relativamente economica, ma non è gratuita. Copiare piccole strutture in giro è relativamente economico, ma non è gratuito. Esistono scenari di prestazioni realistici in cui è necessario bilanciare il costo della pressione di raccolta con il costo di una copia eccessiva. In questi casi è molto utile avere una buona comprensione delle dimensioni, della posizione e della durata effettiva di tutta la memoria pertinente.

Allo stesso modo, ci sono scenari di interoperabilità realistici in cui è necessario sapere cosa c'è nello stack e cosa c'è nell'heap, e cosa potrebbe muoversi il garbage collector. Ecco perché C # ha caratteristiche come "fisso", "stackalloc" e così via.

Ma quelli sono tutti scenari avanzati. Idealmente, un programmatore principiante non dovrebbe preoccuparsi di nulla di tutto questo.

    
risposta data 09.11.2010 - 17:03
fonte
13

A tutti voi manca il punto. Il motivo per cui la distinzione stack / heap è importante è a causa di scope .

struct S { ... }

void f() {
    var x = new S();
    ...
 }

Una volta che x non rientra nell'ambito, l'oggetto che è stato creato è categoricamente gone . Questo è solo perché è allocato nello stack, non nell'heap. Non c'è nulla che potrebbe essere entrato nella parte "..." del metodo che può cambiare questo fatto. In particolare, qualsiasi incarico o chiamata al metodo avrebbe potuto fare solo copie della struttura S, non creare nuovi riferimenti ad essa per consentirgli di continuare a vivere.

class C { ... }

void f() {
     var x = new C();
     ...
}

Storia completamente diversa! Poiché x ora si trova nel heap , il suo oggetto (ovvero l'oggetto stesso , non una copia di esso) potrebbe continuare a vivere dopo x va oltre lo scopo. In effetti, l'unico modo in cui non continuerà a vivere è se x è l'unico riferimento ad esso. Se gli incarichi o le chiamate di metodo nella parte "..." hanno creato altri riferimenti che sono ancora "in diretta" quando x esce dall'ambito, allora quell'oggetto continuerà a vivere.

Questo è un concetto molto importante e l'unico modo per capire veramente "cosa e perché" è conoscere la differenza tra l'allocazione dello stack e dell'heap.

    
risposta data 16.11.2010 - 14:16
fonte
5

Per quanto riguarda l'argomento, sono d'accordo con @Kirk che è un concetto importante, che devi capire. Quanto meglio conosci i meccanismi, tanto meglio puoi fare per rendere grandi le applicazioni che funzionano senza intoppi.

Ora Eric Lippert sembra essere d'accordo con te sul fatto che l'argomento non è trattato correttamente dalla maggior parte degli autori. Ti consiglio di leggere il suo blog per ottenere una buona comprensione di cosa c'è sotto il cofano.

    
risposta data 03.11.2010 - 19:02
fonte
5

Bene, ho pensato che fosse il punto centrale degli ambienti gestiti. Andrei anche fino a chiamare questo un dettaglio di implementazione del runtime sottostante che NON dovresti fare ipotesi, perché potrebbe cambiare in qualsiasi momento.

Non ne so molto su .NET, ma per quanto ne so, è JITted prima dell'esecuzione. Ad esempio, la JIT potrebbe eseguire analisi di escape e cosa no e all'improvviso ti piacerebbe avere oggetti sdraiati su la pila o semplicemente in alcuni registri. Non puoi saperlo.

Suppongo che alcuni libri lo riguardino semplicemente perché gli autori attribuiscono grande importanza a questo, o perché assumono che il loro pubblico lo faccia (ad esempio se hai scritto un "C # per programmatori C ++" probabilmente dovresti coprire l'argomento).

Tuttavia, penso che non ci sia molto altro da dire che "la memoria è gestita". Altrimenti le persone potrebbero trarre conclusioni errate.

    
risposta data 03.11.2010 - 19:02
fonte
2

Devi capire come funziona l'allocazione della memoria per usarlo in modo efficiente anche se non devi gestirlo esplicitamente. Questo si applica a quasi tutte le astrazioni dell'informatica.

    
risposta data 03.11.2010 - 18:53
fonte
2

Ci possono essere alcuni casi limite in cui ciò può fare la differenza. Lo stack space predefinito è 1meg mentre l'heap è di diverse dimensioni. Quindi, se la tua soluzione contiene un numero elevato di oggetti, puoi esaurire lo spazio di stack pur avendo un sacco di spazio disponibile.

Tuttavia, per la maggior parte è piuttosto accademico.

    
risposta data 03.11.2010 - 22:08
fonte
0

Come dici tu, C # dovrebbe estrapolare la gestione della memoria, e l'heap e l'allocazione dello stack sono dettagli di implementazione che in teoria lo sviluppatore non dovrebbe aver bisogno di sapere.

Il problema è che alcune cose sono davvero difficili da spiegare in modo intuitivo senza fare riferimento a questi dettagli di implementazione. Cerca di spiegare il comportamento osservabile quando modifichi i tipi di valore mutabili: è quasi impossibile fare a meno di fare riferimento alla distinzione stack / heap. O prova a spiegare perché anche i tipi di valore nella lingua sono in primo luogo e quando li useresti? Devi capire la distinzione per dare un senso alla lingua.

Si noti che i libri che parlano di Python o JavaScript non fanno un grosso problema se lo menzionano. Questo perché tutto è o heap allocato o immutabile, il che significa che le diverse semantiche di copia non entrano mai in gioco. In quelle lingue funziona l'astrazione della memoria, in C # perde.

    
risposta data 30.08.2016 - 08:23
fonte

Leggi altre domande sui tag