Was ist ein Segmentierungsfehler? Ist er in C und C++ unterschiedlich? Wie hängen Segmentierungsfehler und "Dangling Pointer" zusammen?
Antworten
Zu viele Anzeigen?A Segmentierungsfehler (manchmal auch bekannt als Segfault ) geschieht wenn Ihr Programm versucht, auf Speicher zuzugreifen, auf den es nicht zugreifen darf Mit anderen Worten, wenn Ihr Programm versucht, auf Speicher zuzugreifen, der die Grenzen überschreitet, die das Betriebssystem für Ihr Programm festgelegt hat, ist dies ein häufiger Umstand, der zum Absturz von Programmen führt und häufig mit einer Datei namens core zusammenhängt.
Der Programmspeicher ist in verschiedene Segmente unterteilt:
- ein Textsegment für Programmanweisungen
- ein Datensegment für Variablen und Arrays, die zur Kompilierzeit definiert werden
- ein Stapelsegment für temporäre (oder automatische) Variablen, die in Unterprogrammen und Funktionen definiert sind
- ein Heap-Segment für Variablen, die während der Laufzeit durch Funktionen wie malloc (in C) und allocate (in Fortran) zugewiesen werden.
Wenn ein Verweis auf eine Variable über das Segment hinausgeht, in dem diese Variable existiert, oder wenn versucht wird, an eine Stelle zu schreiben, die sich in einem schreibgeschützten Segment befindet, tritt ein Segfault auf. In der Realität werden Segfaults fast immer dadurch verursacht, dass versucht wird, ein nicht existierendes Array-Mitglied zu lesen oder zu schreiben, dass ein Zeiger nicht korrekt definiert wird, bevor er verwendet wird, oder dass (in C-Anwendungen) versehentlich der Wert einer Variablen als Adresse verwendet wird (siehe das Scan-Beispiel unten).
* Der Aufruf von memset() würde zum Beispiel zu einem Programmfehler (Segfault) führen:
memset((char *)0x0, 1, 100);
* Die drei folgenden Beispiele zeigen die häufigsten Arten von Array-bezogenen Seg-Fehlern:
Fall A
/* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */
int foo[1000]; for (int i = 0; i <= 1000 ; i++) foo[i] = i;
Fall B
/* Illegal memory access if value of n is not in the range 0, 1, ... 999 */
int n; int foo[1000]; for (int i = 0; i < n ; i++) foo[i] = i;
Fall C
/* Illegal memory access because no memory is allocated for foo2 */
float *foo, *foo2; foo = (float*)malloc(1000); foo2[0] = 1.0;
- Im Fall A, Array foo ist definiert für index = 0, 1, 2, ... 999 . In der letzten Iteration der Studie für Schleife, versucht das Programm, auf foo[1000] . Dies führt zu einem Segfault, wenn diese Speicherstelle außerhalb des Speichersegments liegt, in dem foo Residenzen. Selbst wenn es keinen Segfault verursacht, ist es immer noch ein Fehler.
- Im Fall B, Ganzzahl n kann ein beliebiger Zufallswert sein. Wie im Fall A, wenn er nicht im Bereich 0, 1, ... 999 kann es zu einem Segfault kommen. Ob das nun der Fall ist oder nicht, es ist auf jeden Fall ein Fehler.
- Im Fall C ist die Zuweisung von Speicherplatz für die Variable foo2 wurde übersehen, daher foo2 zeigt auf eine zufällige Stelle im Speicher. Zugriff auf foo2[0] wird wahrscheinlich zu einem Segfault führen.
* Ein weiteres typisches Programmierproblem, das Seg-Fehler verursacht, ist die unsachgemäße Verwendung von Zeigern. Die C-Funktion scanf() zum Beispiel benötigt die Adresse einer Variablen als zweiten Parameter; daher wird das Folgende mit großer Sicherheit dazu führen, dass das Programm mit einem Segfault fehlschlägt:
int foo = 0; scanf("%d", foo);
/* Note missing & sign ; correct usage would have been &foo */
Obwohl die Variable foo an der Speicherposition 1000 angelegt werden kann, würde der vorangehende Funktionsaufruf versuchen, Integer-Werte in Übereinstimmung mit der Definition von foo in die Speicherposition 0 zu lesen.
Ein Segfault tritt auf, wenn eine Software versucht, einen Speicherbereich auf unzulässige Weise zu bearbeiten (z.B. würde der Versuch, einen schreibgeschützten Speicherplatz zu beschreiben, zu einem Segfault führen).Wenn Ihre Anwendung keinen Stack-Platz mehr hat, können Segfaults auftreten. Dies kann darauf zurückzuführen sein, dass die Shell die Stack-Größe zu niedrig angesetzt hat, und nicht auf einen Fehler in Ihrer Software.
Dangling Pointers auf etwas hinweisen, das nicht mehr existiert. Ein Dangling Pointer ist ein Beispiel dafür.
char *ptr = NULL;
{
char c;
ptr = &c; //After the block is over, ptr will be a dangling pointer.
}
Am Ende des Blocks erlischt der Geltungsbereich der Variablen c. Da sie nun auf etwas zeigt, das nicht existiert, wird "ptr" zu einem "Dangling Pointer".
Wenn Sie jedoch versuchen, auf Speicher zuzugreifen, der Ihnen nicht gehört, oder wenn Sie versuchen, in einen schreibgeschützten Bereich zu schreiben, erhalten Sie eine Segmentierungsfehler .
char *str ="Testing Seg fault.";
*str= "I hate Seg fault :( ";
str' wird vom Compiler zu einer Konstanten gemacht. Sie ändern den schreibgeschützten Teil, wenn Sie versuchen, den Wert zu aktualisieren, was zu einem Segmentierungsfehler führt.
Ein Segmentierungsfehler oder eine Zugriffsverletzung tritt auf, wenn ein Programm versucht, auf einen Speicherplatz zuzugreifen, der nicht vorhanden ist, oder versucht, auf einen Speicherplatz in einer Weise zuzugreifen, die nicht erlaubt ist.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Hier ist i[1000] nicht vorhanden, daher tritt ein Segfault auf.
Ursachen für Segmentierungsfehler:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).
- See previous answers
- Weitere Antworten anzeigen