Cos'è un segmentation fault?
Un segmentation fault (errore di segmentazione o segfault) è un crash che avviene quando un programma prova a leggere o scrivere memoria a cui non ha il permesso di accedere, come l'indirizzo 0 tramite un puntatore nullo. Il sistema operativo ferma il programma con il segnale SIGSEGV.
Aggiornato il 24 settembre 2026
Un programma in C stampa la sua prima riga e poi si ferma con un messaggio che nessuno ha scritto:
#include <stdio.h>
int main(void) {
int *score = NULL;
printf("About to read the score\n");
printf("Score: %d\n", *score);
return 0;
}
About to read the score
bash: line 1: 64030 Segmentation fault: 11 ./seg
Quell'output viene da bash su macOS, dove 64030 è l'ID del processo e 11 è il numero del segnale. Su Linux lo stesso crash di solito appare come Segmentation fault (core dumped) (su un sistema in italiano, "Errore di segmentazione (core dump creato)"). In ogni caso, il programma non ha mai stampato il punteggio. score contiene l'indirizzo 0, e *score chiede al processore di leggere la memoria a quell'indirizzo, cosa che nessun programma può fare.
Come si verifica un segmentation fault
Ogni programma gira nel proprio spazio di indirizzi virtuale, un enorme intervallo di indirizzi che il sistema operativo riempie pezzo per pezzo. Vi mappa il codice del programma, le sue variabili globali, il suo stack e il suo heap, in blocchi chiamati pagine (4 KB sulla maggior parte dei sistemi Linux x86, 16 KB sui Mac con Apple silicon). La maggior parte degli indirizzi resta non mappata, e l'indirizzo 0 è sempre tra questi, così i bug con i puntatori nulli vengono intercettati.
- Il programma esegue un'istruzione che legge o scrive un indirizzo. Qui è la lettura di
*score, l'indirizzo 0. - L'unità di gestione della memoria del processore cerca l'indirizzo nella tabella delle pagine. La pagina non è mappata, oppure il programma sta provando a scrivere su una pagina di sola lettura.
- Il processore interrompe l'istruzione e passa il controllo al kernel con un page fault.
- Il kernel verifica se l'accesso potrebbe essere lecito, per esempio uno stack che deve crescere. Non lo è, quindi il kernel invia al processo il segnale 11,
SIGSEGV. - L'azione predefinita per
SIGSEGVè terminare il processo e, quando il sistema lo consente, salvare un core dump. La shell poi stampa il messaggio e imposta il codice di uscita a 139, cioè 128 più il numero del segnale.
Quindi un segmentation fault non viene segnalato dal compilatore, e non è un'eccezione sollevata dal linguaggio. Sono l'hardware e il kernel che proteggono la memoria, il che lo rende un errore di runtime del tipo più brusco. Windows tratta lo stesso evento come una access violation, con codice di eccezione 0xC0000005.
Cause comuni dei segmentation fault
C e C++ permettono a un programma di calcolare qualsiasi indirizzo e di usarlo, quindi tutte le cause si riducono all'uso di un indirizzo non valido.
- Dereferenziare un puntatore nullo.
int *p = NULL; *p = 5;Una funzione che restituisceNULLin caso di errore, comemallocofopen, porta qui quando il suo risultato non viene controllato. - Un indice molto oltre la fine di un array. Il C non controlla i limiti, quindi
arr[1000000]è semplicemente un indirizzo un milione di elementi più avanti. - Usare la memoria dopo
free. Il puntatore contiene ancora il vecchio indirizzo, ma la memoria non ti appartiene più. - Un puntatore non inizializzato.
int *p; *p = 5;scrive attraverso il valore spazzatura chepcontiene in quel momento. - Stack overflow. Una funzione ricorsiva senza caso di arresto continua ad aggiungere frame allo stack finché non va oltre la fine dello stack. L'esempio qui sotto è andato in crash su macOS con
Segmentation fault: 11e codice di uscita 139. - Scrivere su una stringa letterale.
char *name = "coddy"; name[0] = 'C';prova a modificare memoria di sola lettura. Su Linux è un segfault. Su macOS lo stesso programma si è fermato conBus error: 10, un segnale affine.
#include <stdio.h>
int depth(int n) {
return depth(n + 1) + 1; /* never stops calling itself */
}
int main(void) {
printf("%d\n", depth(0));
return 0;
}
Spesso un piccolo errore non provoca nessun crash, ed è questo a renderlo più pericoloso. Questo ciclo legge un elemento oltre la fine di un array di tre elementi:
#include <stdio.h>
int main(void) {
int scores[3] = {72, 88, 95};
int total = 0;
for (int i = 0; i <= 3; i++) { /* <= reads scores[3] */
total += scores[i];
}
printf("Total: %d\n", total);
return 0;
}
Compilato con Clang su un Mac, ha stampato Total: 256. Il totale corretto è 255. scores[3] erano i 4 byte successivi dello stack, che appartenevano al programma, quindi non c'è stato nessun fault e il valore spazzatura è stato sommato in silenzio. Il sistema operativo ferma solo gli accessi a memoria che non appartiene affatto al programma.
La soluzione per entrambi gli errori è la stessa abitudine: sapere quanti elementi ci sono e controllare un puntatore prima di seguirlo.
Best: 95
No scores, nothing to read
Cosa significa "core dumped"
Un core dump è un file che contiene una copia della memoria del programma nel momento del crash. Un debugger può aprirlo in seguito e mostrare esattamente dove si trovava il programma e cosa contenevano le sue variabili: gdb ./app core. Su molte distribuzioni Linux è systemd-coredump a raccogliere questi file, e coredumpctl list li mostra. Quando i core dump sono disattivati, per esempio con ulimit -c 0, il messaggio è solo Segmentation fault, senza le parole tra parentesi.
Come trovare la riga del crash
La riga in cui il programma va in crash spesso non è quella che contiene il bug. Un puntatore può diventare non valido in una funzione ed essere usato in un'altra molto più tardi. Questi strumenti mostrano entrambe le cose.
Un debugger. Compila con le informazioni di debug ed esegui il programma dentro il debugger. Quando si ferma, bt (backtrace) stampa la catena di chiamate di funzione con nomi dei file e numeri di riga. Su Linux il debugger è di solito gdb; su macOS è lldb, dove bt funziona allo stesso modo.
gcc -g app.c -o app
gdb ./app
(gdb) run
(gdb) bt
AddressSanitizer. Compila con -fsanitize=address (lo supportano sia GCC sia Clang) ed esegui il programma normalmente. Invece di un semplice segfault, stampa un report che indica il tipo di errore, come heap-use-after-free o stack-buffer-overflow, con la riga che ha fatto l'accesso e la riga che ha allocato la memoria. Intercetta anche la lettura silenziosa di un elemento in più dell'esempio precedente, che da sola non provoca mai un crash.
Valgrind. Su Linux, valgrind ./app esegue un programma senza modificarlo e segnala ogni lettura o scrittura non valida, come Invalid read of size 4.
Segmentation fault in altri linguaggi
Python, Java e JavaScript controllano ogni indice e ogni riferimento prima di usarli, quindi gli stessi errori diventano eccezioni con messaggi chiari: IndexError o AttributeError in Python, ArrayIndexOutOfBoundsException o NullPointerException in Java, TypeError in JavaScript. Queste si possono catturare con la gestione delle eccezioni. Un segfault non si può gestire così: è un segnale, e un blocco catch del C++ non lo vede.
I programmi Python possono comunque andare in segfault quando fallisce il codice C sottostante. Questa riga chiede a ctypes di leggere l'indirizzo 0:
import ctypes
ctypes.string_at(0)
Eseguito con python3 -X faulthandler, Python 3.12 ha stampato Fatal Python error: Segmentation fault, seguito dalle righe Python che erano in esecuzione. Lo stesso crash avviene quando un'estensione in C o una libreria nativa ha un bug di memoria. Rust segue un'altra strada: il suo compilatore rifiuta, prima di costruire il programma, la maggior parte del codice che potrebbe accedere a memoria non valida.
Cosa leggere dopo
La guida C sui segmentation fault esamina ogni causa con un programma minimo e la relativa soluzione. Per evitare questi errori fin dall'inizio, studia i puntatori, i puntatori nulli e la differenza tra stack e heap, poi mettili in pratica nel corso C. Per vedere come vengono segnalati gli errori nei linguaggi che controllano la memoria al posto tuo, consulta la pagina sull'errore di runtime.
Domande frequenti
Come si risolve un segmentation fault?
-g ed esegui il programma dentro gdb o lldb, poi digita bt dopo il crash, oppure compila con -fsanitize=address per avere un report dettagliato. Poi correggi il puntatore o l'indice usato da quella riga: controlla che i puntatori non siano NULL, tieni gli indici degli array sotto la lunghezza, smetti di usare la memoria dopo free e assicurati che la ricorsione termini.Un segmentation fault è un memory leak?
free, come usare un puntatore dopo averlo liberato, possono causare segfault, mentre dimenticare free causa memory leak.Perché si chiama segmentation fault?
SIGSEGV, sono rimasti. Windows chiama lo stesso evento access violation (violazione di accesso).Python può dare un segmentation fault?
ctypes. Eseguire python -X faulthandler script.py stampa le righe Python che erano in esecuzione al momento del crash.Cosa significa il codice di uscita 139?
SIGSEGV, un segmentation fault. Le shell riportano una terminazione per segnale come 128 più il numero del segnale, e 128 + 11 = 139. In Docker e Kubernetes, un container che esce con 139 ha avuto un segfault nel suo processo principale.