Was ist ein Segmentierungsfehler? Ist es anders in C und C ++? Wie hängen Segmentierungsfehler und baumelnde Zeiger zusammen?
c++
c
segmentation-fault
Rajendra Uppal
quelle
quelle
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:
Ein weiterer Segfault tritt auf, wenn Sie versuchen, in einen Teil des Speichers zu schreiben, der als schreibgeschützt markiert wurde:
Der baumelnde Zeiger zeigt auf etwas, das es nicht mehr gibt, wie hier:
Der Zeiger
p
baumelt, weil er auf eine Zeichenvariable zeigtc
, 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.quelle
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.
quelle
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.
quelle
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
quelle
Laut Wikipedia:
quelle
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
quelle
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.
quelle
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.)
quelle
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.
quelle
"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).
quelle
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.
Hier existiert i [1000] nicht, so dass ein Segfault auftritt.
Ursachen des Segmentierungsfehlers:
quelle
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 hier genommen .
quelle
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.
Ausgabe :
Segmentation Fault (SIGSEGV)
quelle
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&
).printf()
undscanf()
'quelle