Il primo tema su cui ci si soffermerà è l’allocazione della memoria, uno dei punti critici nelle applicazioni di sistema tradizionali. La complessità nell’assegnare, ridistribuire e liberare blocchi di memoria espone il software a fragilità che possono manifestarsi come crash improvvisi o, peggio, vulnerabilità sfruttabili dagli hacker.
Errori di allocazione - come buffer overflow, dangling pointer o memory leak - sono spesso all’origine dei bug più pericolosi. Quando la gestione della memoria non è implementata con rigore, il programma può comportarsi in modo incontrollato, causando instabilità, perdita di dati e gravi problemi di sicurezza.
L’obiettivo è acquisire conoscenze e tecniche necessarie per:
In questo capitolo verrà affrontata una rassegna veloce dei concetti chiave dell’architettura di elaborazione, per comprendere come CPU, memoria e bus interagiscono a basso livello.
Si discuterà quindi dello spazio di indirizzamento, distinguendo tra indirizzamento virtuale e reale, vedendo come il sistema operativo mappa le pagine di memoria in modo trasparente per il programmatore.
Successivamente verrà descritto il modello di esecuzione di un programma, ossia il flusso di controllo e i passaggi necessari dal lancio di un’applicazione all’esecuzione delle sue istruzioni.
Infine, ci si concentrerà su due principali strutture dati in cui si articola la memoria di un processo: lo stack, utilizzato per chiamate di funzione e variabili locali, e lo heap, riservato all’allocazione dinamica. In questo contesto verrà analizzato il ruolo cruciale dei puntatori, evidenziando le problematiche (aliasing, buffer overflow, dangling pointer) che ne possono derivare.
Un programma eseguibile è un’unità di istruzioni macchina, dati e valori di configurazione codificati come sequenze di numeri binari. Il significato di ciascuna istruzione è “cablato” nell’archiettura del processore per cui il programma è stato compilato: ad esempio, un byte specifico può corrispondere a un’operazione di caricamento di un immediato in un registro. Altre parti del file - come l’header “shebang” in ambiente Unix - vengono interpretate dal sistema operativo per avviare script o decidere come gestire il caricamento.
Per poter essere eseguito, un programma deve risiedere in uno spazio di memoria accessibile al processore.