Come vengono gestite, implementate, allocate le memorie heap e stack?

In C / C ++ possiamo memorizzare variabili, funzioni, funzioni membro, istanze di una class su uno stack o su un heap.

Come sono implementati? Come è gestito (alto livello)? Gcc prealloca un blocco di memoria da utilizzare per lo stack e l’heap, quindi distribuisce su richiesta? La memoria originale proviene dalla RAM?

È ansible allocare una funzione sull’heap anziché su uno stack?

Una precisazione

Mi sto veramente chiedendo di implementare e gestire le memorie heap e stack. Dopo aver letto la domanda di riferimento, non ho trovato nulla che si riferisse a … grazie per il link

    I moderni sistemi operativi non ti danno accesso diretto alla RAM hardware e invece la astraggono nella cosiddetta memoria virtuale, che associa alla RAM su richiesta. Di solito a ogni processo viene fornita una copia privata dello spazio di indirizzamento completo. Ciò consente al sistema operativo di spostare la memoria di un processo nella RAM in fase di esecuzione o persino di sostituirla su disco. Ciò avviene in modo trasparente, ovvero un processo non viene informato di tale trasferimento e non ha bisogno di avere il codice per gestirlo. (Alcune applicazioni in tempo reale potrebbero utilizzare tecniche per impedire che la memoria venga scambiata).

    Quando colleghi i file object a un eseguibile o una libreria dynamic, il linker assegna staticamente memoria per le istruzioni cpu di una funzione / metodo e per tutte le variabili globali. Quando l’os carica la libreria eseguibile o dynamic, mappa questa memoria pre-allocata nella memoria reale.

    All’avvio, ogni thread riceve un’area di memoria privata chiamata stack. Ogni volta che si chiama una funzione / metodo, il compilatore inserisce il codice per allocare automaticamente (incrementando il puntatore dello stack) abbastanza memoria dallo stack per contenere tutti i parametri, le variabili locali e il valore di ritorno (se presente) utilizzato dalla funzione / metodo. Se il compilatore determina che è sufficiente lasciare alcune variabili nei registri del processore, non alloca memoria nello stack per esso. Quando la funzione / metodo ritorna, esegue il codice generato dal compilatore per liberare (decrementando il puntatore dello stack) questa memoria. Nota che i distruttori di tutti gli oggetti nello stack saranno chiamati quando il blocco in cui sono definiti in uscita, che potrebbe essere molto tempo prima di tornare. Inoltre, il compilatore è libero di riutilizzare la memoria allacated come meglio crede.

    Quando viene generata un’eccezione, il compilatore del compilatore inserisce un codice speciale che conosce il layout dello stack e che può svolgerlo fino a trovare un gestore di eccezioni adatto.

    A differenza di ciò, la memoria sull’heap viene allocata usando new / delete , per cui il compilatore inserisce il codice per richiedere o rilasciare memoria utilizzando una libreria di sistema.

    Si noti che questa è una descrizione semplificata per darvi un’idea di come funziona l’allocazione della memoria.

    Fondamentalmente l’heap non è implementato dal compilatore, ma dalla libreria di runtime C. Ovviamente questo codice è molto dipendente dalla piattaforma. Sui sistemi Unix o Unix l’implementazione è generalmente basata sulla chiamata di sistema sbrk / brk e viene allocata una quantità maggiore di memoria per ridurre il numero di chiamate di sistema. Questa memoria viene quindi gestita dal gestore della memoria heap. Se è necessaria più memoria, viene emessa una nuova chiamata a sbrk. L’indirizzo finale corrente dell’heap può essere ottenuto con sbrk (0) se si è interessati al debug delle routine di gestione dell’heap. La maggior parte dei gestori di memoria non restituiscono memoria al sistema operativo durante il ciclo di vita di un processo (la libreria di runtime di gnu c viene eseguita se vengono soddisfatti determinati vincoli).

    Una descrizione più dettagliata è disponibile in http://gee.cs.oswego.edu/dl/html/malloc.html .