Was ist ein Segmentation Fault?
Ein Segmentation Fault, kurz Segfault, ist ein Absturz, der passiert, wenn ein Programm Speicher lesen oder schreiben will, auf den es nicht zugreifen darf, etwa Adresse 0 über einen Nullzeiger. Das Betriebssystem beendet das Programm mit dem Signal SIGSEGV.
Aktualisiert am 24. September 2026
Ein C-Programm gibt seine erste Zeile aus und hält dann mit einer Meldung an, die niemand geschrieben hat:
#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
Diese Ausgabe stammt von bash unter macOS; 64030 ist die Prozess-ID und 11 die Signalnummer. Unter Linux lautet derselbe Absturz meist Segmentation fault (core dumped), auf einem deutsch eingestellten System Speicherzugriffsfehler (Speicherabzug geschrieben). So oder so hat das Programm die Punktzahl nie ausgegeben. score enthält die Adresse 0, und *score fordert den Prozessor auf, den Speicher an dieser Adresse zu lesen, was kein Programm darf.
Wie ein Segmentation Fault entsteht
Jedes Programm läuft in seinem eigenen virtuellen Adressraum, einem riesigen Bereich von Adressen, den das Betriebssystem Stück für Stück füllt. Es bildet Code, globale Variablen, Stack und Heap des Programms in diesen Bereich ab, in Blöcken namens Seiten (4 KB auf den meisten x86-Linux-Systemen, 16 KB auf Macs mit Apple Silicon). Die meisten Adressen bleiben unbelegt, und Adresse 0 gehört immer dazu, damit Fehler mit Nullzeigern auffallen.
- Das Programm führt eine Anweisung aus, die eine Adresse liest oder beschreibt. Hier ist es das Lesen von
*score, Adresse 0. - Die Speicherverwaltungseinheit (MMU) des Prozessors sucht die Adresse in der Seitentabelle. Die Seite ist nicht abgebildet, oder das Programm will auf eine schreibgeschützte Seite schreiben.
- Der Prozessor bricht die Anweisung ab und übergibt die Kontrolle mit einem Seitenfehler (Page Fault) an den Kernel.
- Der Kernel prüft, ob der Zugriff zulässig sein könnte, zum Beispiel bei einem Stack, der wachsen muss. Das ist er nicht, also schickt der Kernel dem Prozess Signal 11,
SIGSEGV. - Die Standardreaktion auf
SIGSEGVist, den Prozess zu beenden und, wenn das System es erlaubt, einen Core Dump zu speichern. Die Shell gibt dann die Meldung aus und setzt den Exit-Status auf 139, also 128 plus die Signalnummer.
Ein Segmentation Fault wird also nicht vom Compiler gemeldet, und er ist keine Ausnahme, die die Sprache wirft. Hier schützen Hardware und Kernel den Speicher, und das macht ihn zum abruptesten Laufzeitfehler. Windows behandelt dasselbe Ereignis als Zugriffsverletzung mit dem Ausnahmecode 0xC0000005.
Typische Ursachen für Segmentation Faults
C und C++ erlauben einem Programm, jede beliebige Adresse zu berechnen und zu verwenden, also laufen die Ursachen darauf hinaus, eine ungültige Adresse zu benutzen.
- Dereferenzieren eines Nullzeigers.
int *p = NULL; *p = 5;Eine Funktion, die bei einem FehlerNULLzurückgibt, etwamallocoderfopen, führt hierher, wenn ihr Ergebnis nicht geprüft wird. - Ein Index weit hinter dem Ende eines Arrays. C prüft keine Grenzen, also ist
arr[1000000]einfach eine Adresse eine Million Elemente weiter. - Speicher nach
freebenutzen. Der Zeiger enthält noch die alte Adresse, aber der Speicher gehört dir nicht mehr. - Ein nicht initialisierter Zeiger.
int *p; *p = 5;schreibt an den zufälligen Wert, denpgerade enthält. - Stack Overflow. Eine rekursive Funktion ohne Abbruchfall legt immer neue Stack-Frames an, bis sie über das Ende des Stacks hinausläuft. Das Beispiel unten stürzte unter macOS mit
Segmentation fault: 11und Exit-Status 139 ab. - In ein String-Literal schreiben.
char *name = "coddy"; name[0] = 'C';versucht, schreibgeschützten Speicher zu ändern. Unter Linux ist das ein Segfault. Unter macOS hielt dasselbe Programm mitBus error: 10an, einem verwandten Signal.
#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;
}
Ein kleiner Fehler führt oft gar nicht zum Absturz, und das macht ihn gefährlicher. Diese Schleife liest ein Element hinter dem Ende eines Arrays mit drei Elementen:
#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;
}
Mit Clang auf einem Mac kompiliert, gab es Total: 256 aus. Die richtige Summe ist 255. scores[3] waren die nächsten 4 Bytes auf dem Stack, die dem Programm gehörten, also trat kein Fehler auf, und der Müllwert wurde unbemerkt addiert. Das Betriebssystem stoppt nur Zugriffe auf Speicher, der dem Programm überhaupt nicht gehört.
Die Lösung für beide Fehler ist dieselbe Gewohnheit: Wisse, wie viele Elemente es gibt, und prüf einen Zeiger, bevor du ihm folgst.
Best: 95
No scores, nothing to read
Was "core dumped" bedeutet
Ein Core Dump (Speicherabzug) ist eine Datei mit einer Kopie des Programmspeichers im Moment des Absturzes. Ein Debugger kann sie später öffnen und genau zeigen, wo das Programm war und welche Werte seine Variablen hatten: gdb ./app core. Auf vielen Linux-Distributionen sammelt systemd-coredump diese Dateien, und coredumpctl list zeigt sie an. Sind Core Dumps abgeschaltet, zum Beispiel mit ulimit -c 0, lautet die Meldung nur Segmentation fault, ohne die Wörter in Klammern.
Wie du die Zeile findest, die abgestürzt ist
Die Zeile, in der das Programm abstürzt, ist oft nicht die Zeile mit dem Bug. Ein Zeiger kann in einer Funktion ungültig werden und viel später in einer anderen benutzt werden. Diese Werkzeuge zeigen beides.
Ein Debugger. Kompiliere mit Debug-Informationen und führ das Programm im Debugger aus. Hält es an, gibt bt (Backtrace) die Kette der Funktionsaufrufe mit Dateinamen und Zeilennummern aus. Unter Linux ist der Debugger meist gdb, unter macOS lldb, wo bt genauso funktioniert.
gcc -g app.c -o app
gdb ./app
(gdb) run
(gdb) bt
AddressSanitizer. Kompiliere mit -fsanitize=address (GCC und Clang unterstützen es beide) und führ das Programm normal aus. Statt eines nackten Segfaults gibt es einen Bericht aus, der die Art des Fehlers nennt, etwa heap-use-after-free oder stack-buffer-overflow, mit der Zeile, die zugegriffen hat, und der Zeile, die den Speicher reserviert hat. Er findet auch das stille Lesen hinter dem Ende von oben, das von allein nie abstürzt.
Valgrind. Unter Linux führt valgrind ./app ein unverändertes Programm aus und meldet jedes ungültige Lesen oder Schreiben, etwa Invalid read of size 4.
Segmentation Faults in anderen Sprachen
Python, Java und JavaScript prüfen jeden Index und jede Referenz vor der Verwendung, also werden dieselben Fehler zu Ausnahmen mit klaren Meldungen: IndexError oder AttributeError in Python, ArrayIndexOutOfBoundsException oder NullPointerException in Java, TypeError in JavaScript. Die lassen sich mit Ausnahmebehandlung fangen. Ein Segfault lässt sich so nicht behandeln: Er ist ein Signal, und ein catch-Block in C++ sieht ihn nicht.
Python-Programme können trotzdem abstürzen, wenn C-Code unter ihnen versagt. Diese Zeile lässt ctypes die Adresse 0 lesen:
import ctypes
ctypes.string_at(0)
Mit python3 -X faulthandler ausgeführt, gab Python 3.12 Fatal Python error: Segmentation fault aus, gefolgt von den Python-Zeilen, die gerade liefen. Derselbe Absturz passiert, wenn eine C-Erweiterung oder eine native Bibliothek einen Speicherfehler hat. Rust geht einen anderen Weg: Sein Compiler lehnt den meisten Code, der auf ungültigen Speicher zugreifen könnte, schon vor dem Bauen ab.
Wie es weitergeht
Die C-Anleitung zu Segmentation Faults geht jede Ursache mit einem minimalen Programm und seiner Lösung durch. Um die Fehler gar nicht erst zu machen, lies über Zeiger, Nullzeiger und Stack und Heap und üb sie dann im C-Kurs. Wie Fehler in Sprachen gemeldet werden, die den Speicher für dich prüfen, zeigt die Seite zu Laufzeitfehler.
Häufig gestellte Fragen
Wie behebt man einen Segmentation Fault?
-g und führ das Programm unter gdb oder lldb aus, tipp nach dem Absturz bt, oder kompiliere mit -fsanitize=address für einen ausführlichen Bericht. Dann korrigier den Zeiger oder Index, den diese Zeile verwendet: Prüf Zeiger auf NULL, halte Array-Indizes unter der Länge, benutz keinen Speicher mehr nach free und sorg dafür, dass Rekursion endet.Ist ein Segmentation Fault ein Speicherleck?
free, etwa einen Zeiger nach dem Freigeben weiter zu benutzen, können Segfaults auslösen, ein vergessenes free dagegen Lecks.Warum heißt es Segmentation Fault?
SIGSEGV sind geblieben. Windows nennt dasselbe Ereignis eine Zugriffsverletzung (Access Violation).Kann es in Python einen Segmentation Fault geben?
ctypes. python -X faulthandler script.py gibt die Python-Zeilen aus, die beim Absturz liefen.Was bedeutet Exit-Code 139?
SIGSEGV, einen Segmentation Fault. Shells melden einen Tod durch ein Signal als 128 plus Signalnummer, und 128 + 11 = 139. In Docker und Kubernetes bedeutet ein Container mit Exit-Code 139, dass sein Hauptprozess einen Segfault hatte.