Lo stack e l'heap in C / C ++ descrivono diversi meccanismi di allocazione della memoria. Possono anche essere chiamati "archiviazione automatica" e "negozio gratuito". Se si assegnano i dati sullo store / heap liberi, si è responsabili della gestione della durata (chiamando delete
o free()
). Questo è in gran parte non correlato alle pagine di memoria.
Le pagine di memoria sono un blocco di indirizzi virtuali. Lo spazio di indirizzamento virtuale di un processo viene creato dal sistema operativo mappando le pagine nello spazio degli indirizzi.
Un processo utilizza diverse aree dello spazio degli indirizzi in modo diverso. Un'area sarà la pila. Altre aree manterranno il contenuto di file e librerie eseguibili. Questi file possono avere segmenti diversi, ad es. per codice eseguibile, per costanti e spazio per variabili.
Qui ho richiamato le mappature dello spazio degli indirizzi di un interprete Perl usando pmap:
0000000000400000 1776K r-x-- perl
00000000007bb000 4K r---- perl
00000000007bc000 12K rw--- perl
00000000007bf000 4K rw--- [ anon ]
0000000001eff000 1192K rw--- [ anon ]
00007f00184b7000 4464K r---- locale-archive
00007f0018913000 1792K r-x-- libc-2.23.so
00007f0018ad3000 2048K ----- libc-2.23.so
00007f0018cd3000 16K r---- libc-2.23.so
00007f0018cd7000 8K rw--- libc-2.23.so
00007f0018cd9000 16K rw--- [ anon ]
00007f0018cdd000 36K r-x-- libcrypt-2.23.so
00007f0018ce6000 2044K ----- libcrypt-2.23.so
00007f0018ee5000 4K r---- libcrypt-2.23.so
00007f0018ee6000 4K rw--- libcrypt-2.23.so
00007f0018ee7000 184K rw--- [ anon ]
00007f0018f15000 1056K r-x-- libm-2.23.so
00007f001901d000 2044K ----- libm-2.23.so
00007f001921c000 4K r---- libm-2.23.so
00007f001921d000 4K rw--- libm-2.23.so
00007f001921e000 12K r-x-- libdl-2.23.so
00007f0019221000 2044K ----- libdl-2.23.so
00007f0019420000 4K r---- libdl-2.23.so
00007f0019421000 4K rw--- libdl-2.23.so
00007f0019422000 96K r-x-- libpthread-2.23.so
00007f001943a000 2044K ----- libpthread-2.23.so
00007f0019639000 4K r---- libpthread-2.23.so
00007f001963a000 4K rw--- libpthread-2.23.so
00007f001963b000 16K rw--- [ anon ]
00007f001963f000 152K r-x-- ld-2.23.so
00007f0019839000 20K rw--- [ anon ]
00007f0019864000 4K r---- ld-2.23.so
00007f0019865000 4K rw--- ld-2.23.so
00007f0019866000 4K rw--- [ anon ]
00007ffc0cd0a000 136K rw--- [ stack ]
00007ffc0cd4e000 12K r---- [ anon ]
00007ffc0cd51000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 21284K
Si noti che la dimensione più piccola è 4K, cioè la dimensione della pagina sul mio sistema.
Possiamo vedere nella colonna più a destra quali file (eseguibili o librerie) sono stati mappati nello spazio degli indirizzi a cui è stato eseguito l'offset. Esistono anche un paio di regioni speciali, come [stack]
. Alcune delle regioni anonime possono essere utilizzate come archivio / heap gratuito. Ci possono essere spazi tra gli intervalli mappati dello spazio degli indirizzi. Provare ad accedere alla memoria in un intervallo non associato causerà un segfault.
Ciascuna di queste regioni è composta da una o più pagine. Questo è importante, perché le pagine possono avere protezioni di accesso: i file eseguibili e le librerie forniscono pagine eseguibili per codice, pagine di sola lettura per le costanti e pagine di lettura-scrittura per variabili. Questo è un meccanismo di sicurezza per evitare l'esecuzione di dati arbitrari (anche se questo non è molto importante per un interprete ). Le pagine per l'heap e lo stack saranno leggibili e scrivibili, ma non eseguibili.
Un intervallo di indirizzi può essere mappato, ma la pagina per quell'indirizzo potrebbe non esistere al momento. L'utilizzo di tale indirizzo attiverà un errore di pagina. Il sistema operativo può intercettare l'errore di pagina e aggiungere la pagina. Ad esempio, non tutte le pagine del 136 K per lo stack possono esistere all'avvio del processo. Invece, le pagine vengono aggiunte su richiesta. Oppure, una pagina potrebbe essere stata scambiata su disco. Un errore di pagina causerà il caricamento di quella pagina nella memoria fisica.