Was ist ein Segmentierungsfehler? Ist es anders in C und C ++? Wie hängen Segmentierungsfehler und baumelnde Zeiger zusammen?
NullPointerException
.
Was ist ein Segmentierungsfehler? Ist es anders in C und C ++? Wie hängen Segmentierungsfehler und baumelnde Zeiger zusammen?
NullPointerException
.
Antworten:
Ein Segmentierungsfehler ist eine bestimmte Art von Fehler, der durch den Zugriff auf Speicher verursacht wird, der „Ihnen nicht gehört“. Es ist ein Hilfsmechanismus, der Sie davon abhält, den Speicher zu beschädigen und schwer zu debuggende Speicherfehler einzuführen. Immer wenn Sie einen Segfault erhalten, wissen Sie, dass Sie mit dem Speicher etwas falsch machen - auf eine bereits freigegebene Variable zugreifen, in einen schreibgeschützten Teil des Speichers schreiben usw. Der Segmentierungsfehler ist in den meisten Sprachen, mit denen Sie sich herumschlagen können, im Wesentlichen der gleiche Bei der Speicherverwaltung gibt es keinen grundsätzlichen Unterschied zwischen Segfaults in C und C ++.
Es gibt viele Möglichkeiten, einen Segfault zu erhalten, zumindest in den untergeordneten Sprachen wie C (++). Ein üblicher Weg, um einen Segfault zu erhalten, besteht darin, einen Nullzeiger zu dereferenzieren:
int *p = NULL;
*p = 1;
Ein weiterer Segfault tritt auf, wenn Sie versuchen, in einen Teil des Speichers zu schreiben, der als schreibgeschützt markiert wurde:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Der baumelnde Zeiger zeigt auf etwas, das es nicht mehr gibt, wie hier:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Der Zeiger p
baumelt, weil er auf eine Zeichenvariable zeigt c
, die nach dem Ende des Blocks nicht mehr existiert. Und wenn Sie versuchen, einen baumelnden Zeiger (wie *p='A'
) zu dereferenzieren , erhalten Sie wahrscheinlich einen Segfault.
c
lokal ist. Dies bedeutet, dass es nachher auf den Stapel geschoben {
und danach herausgepoppt wurde }
. Der baumelnde Zeiger ist nur eine Referenz auf einen Versatz, der sich jetzt außerhalb des Stapels befindet. Aus diesem Grund wird das Ändern in einem einfachen Programm niemals einen Segfault auslösen. Andererseits kann es in einem komplexeren Anwendungsfall zu einem Segfault kommen, bei dem andere Funktionsaufrufe dazu führen können, dass der Stapel wächst und die Daten enthält, auf die der baumelnde Zeiger zeigt. Das Schreiben auf diese Daten (lokale Variablen) würde zu undefiniertem Verhalten führen (Segfault & Co)
SIGSEGV
erwarte ich nicht, dass ein solches Signal den Stapel beschädigt.
Es ist erwähnenswert, dass ein Segmentierungsfehler nicht durch den direkten Zugriff auf einen anderen Prozessspeicher verursacht wird (das höre ich manchmal), da dies einfach nicht möglich ist. Mit virtuellem Speicher hat jeder Prozess seinen eigenen virtuellen Adressraum und es gibt keine Möglichkeit, mit einem Zeigerwert auf einen anderen zuzugreifen. Eine Ausnahme bilden gemeinsam genutzte Bibliotheken, bei denen es sich um denselben physischen Adressraum handelt, der (möglicherweise) verschiedenen virtuellen Adressen zugeordnet ist, und um Kernelspeicher, die in jedem Prozess sogar auf dieselbe Weise zugeordnet werden (um zu vermeiden, dass TLB bei syscall geleert wird, denke ich). Und Dinge wie shmat;) - das zähle ich als "indirekten" Zugang. Man kann jedoch überprüfen, ob sie sich normalerweise weit vom Prozesscode entfernt befinden und wir normalerweise darauf zugreifen können (deshalb sind sie dort,
Dennoch kann ein Segmentierungsfehler auftreten, wenn auf nicht ordnungsgemäße Weise auf unseren eigenen (Prozess-) Speicher zugegriffen wird (z. B. wenn versucht wird, in einen nicht beschreibbaren Speicherplatz zu schreiben). Der häufigste Grund dafür ist jedoch der Zugriff auf den Teil des virtuellen Adressraums, der überhaupt keinem physischen zugeordnet ist.
Und das alles in Bezug auf virtuelle Speichersysteme.
Ein Segmentierungsfehler wird durch eine Anforderung für eine Seite verursacht, die der Prozess nicht in seiner Deskriptortabelle aufgeführt hat, oder durch eine ungültige Anforderung für eine Seite, die er aufgelistet hat (z. B. eine Schreibanforderung auf einer schreibgeschützten Seite).
Ein baumelnder Zeiger ist ein Zeiger, der auf eine gültige Seite zeigen kann oder nicht, aber auf ein "unerwartetes" Speichersegment zeigt.
Um ehrlich zu sein, hat Wikipedia, wie andere Poster bereits erwähnt haben, einen sehr guten Artikel dazu. Schauen Sie sich das an. Diese Art von Fehler ist sehr häufig und wird häufig als andere Dinge bezeichnet, z. B. Zugriffsverletzung oder allgemeiner Schutzfehler.
Sie unterscheiden sich nicht in C, C ++ oder einer anderen Sprache, die Zeiger zulässt. Diese Art von Fehlern wird normalerweise durch Zeiger verursacht
Laut Wikipedia:
Ein Segmentierungsfehler tritt auf, wenn ein Programm versucht, auf einen Speicherort zuzugreifen, auf den es nicht zugreifen darf, oder wenn es versucht, auf einen Speicherort zuzugreifen, der nicht zulässig ist (z. B. beim Versuch, an einen schreibgeschützten Speicherort zu schreiben, oder einen Teil des Betriebssystems überschreiben).
Ein Segmentierungsfehler wird auch durch Hardwarefehler verursacht, in diesem Fall die RAM-Speicher. Dies ist die seltenere Ursache. Wenn Sie jedoch keinen Fehler in Ihrem Code finden, kann Ihnen möglicherweise ein Memtest helfen.
Die Lösung in diesem Fall ändern Sie den RAM.
bearbeiten:
Hier gibt es eine Referenz: Segmentierungsfehler nach Hardware
Ein Segmentierungsfehler tritt auf, wenn ein Prozess (eine laufende Instanz eines Programms) versucht, auf die schreibgeschützte Speicheradresse oder den Speicherbereich zuzugreifen, der von einem anderen Prozess verwendet wird, oder auf die nicht vorhandene (ungültige) Speicheradresse zuzugreifen. Dangling Reference (Zeiger) Problem bedeutet, dass versucht wird, auf ein Objekt oder eine Variable zuzugreifen, deren Inhalt bereits aus dem Speicher gelöscht wurde, z.
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Die Segmentation_fault- Seite von Wikipedia enthält eine sehr schöne Beschreibung, in der nur die Ursachen und Gründe aufgezeigt werden. Schauen Sie im Wiki nach einer detaillierten Beschreibung.
Beim Rechnen ist ein Segmentierungsfehler (häufig mit Segfault abgekürzt) oder eine Zugriffsverletzung ein Fehler, der von Hardware mit Speicherschutz ausgelöst wird und ein Betriebssystem (OS) über eine Speicherzugriffsverletzung benachrichtigt.
Im Folgenden sind einige typische Ursachen für einen Segmentierungsfehler aufgeführt:
Diese wiederum werden häufig durch Programmierfehler verursacht, die zu einem ungültigen Speicherzugriff führen:
Dereferenzieren oder Zuweisen zu einem nicht initialisierten Zeiger (wilder Zeiger, der auf eine zufällige Speicheradresse zeigt)
Dereferenzieren oder Zuweisen zu einem freigegebenen Zeiger (baumelnder Zeiger, der auf den freigegebenen / freigegebenen / gelöschten Speicher zeigt)
Ein Pufferüberlauf.
Ein Stapelüberlauf.
Versuch, ein Programm auszuführen, das nicht korrekt kompiliert wird. (Einige Compiler geben trotz Fehlern bei der Kompilierung eine ausführbare Datei aus.)
Mit einfachen Worten: Segmentierungsfehler ist, dass das Betriebssystem ein Signal an das Programm sendet, das besagt, dass es einen unzulässigen Speicherzugriff erkannt hat und das Programm vorzeitig beendet, um zu verhindern, dass der Speicher beschädigt wird.
"Segmentierungsfehler" bedeutet, dass Sie versucht haben, auf Speicher zuzugreifen, auf den Sie keinen Zugriff haben.
Das erste Problem ist mit Ihren Argumenten von main. Die Hauptfunktion sollte sein int main(int argc, char *argv[])
, und Sie sollten überprüfen, ob argc mindestens 2 ist, bevor Sie auf argv [1] zugreifen.
Da Sie ein Float an printf übergeben (das übrigens beim Übergeben an printf in ein Double konvertiert wird), sollten Sie den Formatbezeichner% f verwenden. Der% s-Formatbezeichner gilt für Zeichenfolgen ('\ 0'-terminierte Zeichenarrays).
Ein Segmentierungsfehler oder eine Zugriffsverletzung tritt auf, wenn ein Programm versucht, auf einen nicht vorhandenen Speicherort zuzugreifen, oder wenn versucht wird, auf eine nicht zulässige Weise auf einen Speicherort zuzugreifen.
/* "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 existiert i [1000] nicht, so dass ein Segfault auftritt.
Ursachen des Segmentierungsfehlers:
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).
Es gibt mehrere gute Erklärungen für "Segmentierungsfehler" in den Antworten, aber da bei Segmentierungsfehlern häufig ein Speicherauszug des Speicherinhalts vorhanden ist, wollte ich mitteilen, wo die Beziehung zwischen dem Teil "Kernspeicherauszug" im Segmentierungsfehler (Kernspeicherauszug) und Erinnerung kommt von:
Von etwa 1955 bis 1975 - vor dem Halbleiterspeicher - verwendete die vorherrschende Technologie im Computerspeicher winzige magnetische Donuts, die auf Kupferdrähten aufgereiht waren. Die Donuts waren als "Ferritkerne" und der Hauptspeicher als "Kernspeicher" oder "Kern" bekannt.
Von hier genommen .
Es gibt genügend Definitionen für Segmentierungsfehler. Ich möchte einige Beispiele anführen, die mir beim Programmieren begegnet sind. Diese Fehler mögen albern erscheinen, verschwenden aber viel Zeit.
Im folgenden Fall kann ein Segmentierungsfehler auftreten, wenn der Argumet-Typ in printf nicht übereinstimmt
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
Ausgabe : Segmentation Fault (SIGSEGV)
wenn Sie vergessen haben, einem Zeiger Speicher zuzuweisen, aber versucht haben, ihn zu verwenden.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
Ausgabe : Segmentation Fault (SIGSEGV)
Eine einfache Bedeutung von Segmentation fault
ist, dass Sie versuchen, auf einen Speicher zuzugreifen, der Ihnen nicht gehört. Segmentation fault
tritt auf, wenn wir versuchen, Aufgaben an einem Nur-Lese-Speicherort zu lesen und / oder zu schreiben oder Speicher freizugeben. Mit anderen Worten, wir können dies als eine Art Speicherbeschädigung erklären.
Im Folgenden erwähne ich häufige Fehler von Programmierern, die dazu führen Segmentation fault
.
scanf()
in falschem Weg (vergessen zu setzen &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
und scanf()
'