Was ist ein Segmentierungsfehler? Ist er in C und C++ unterschiedlich? Wie hängen Segmentierungsfehler und "Dangling Pointer" zusammen?
Antworten
Zu viele Anzeigen?Ein Segmentierungsfehler ist eine spezielle Art von Fehler, der durch den Zugriff auf Speicher verursacht wird, der "nicht zu Ihnen gehört". Es handelt sich um einen Hilfsmechanismus, der verhindert, dass Sie den Speicher beschädigen und schwer zu debuggende Speicherfehler einführen. Wann immer ein Segfault auftritt, wissen Sie, dass Sie etwas Falsches mit dem Speicher tun - auf eine Variable zugreifen, die bereits freigegeben wurde, in einen schreibgeschützten Teil des Speichers schreiben usw. Segmentierungsfehler sind in den meisten Sprachen, in denen man mit der Speicherverwaltung herumspielen kann, im Wesentlichen gleich, es gibt keinen prinzipiellen Unterschied zwischen Segfault in C und C++.
Es gibt viele Möglichkeiten, einen Segfault zu bekommen, zumindest in den niedrigeren Sprachen wie C(++). Ein üblicher Weg, einen Segfault zu bekommen, ist die Dereferenzierung eines Null-Zeigers:
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
Dangling Pointer verweist auf eine Sache, die nicht mehr existiert, wie hier:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Der Zeiger p
baumelt, weil sie auf die Zeichenvariable c
die nach Beendigung des Blocks nicht mehr existieren. Und wenn Sie versuchen, Dangling Pointer zu derefenzieren (wie *p='A'
), würden Sie wahrscheinlich einen Segfault erhalten.
Es wäre erwähnenswert, dass ein Segmentierungsfehler nicht durch direkten Zugriff auf den Speicher eines anderen Prozesses verursacht wird (wie ich manchmal höre), 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 beliebigen Zeigerwert auf einen anderen zuzugreifen. Eine Ausnahme bilden gemeinsam genutzte Bibliotheken, bei denen derselbe physikalische Adressraum auf (möglicherweise) unterschiedliche virtuelle Adressen abgebildet wird, und Kernelspeicher, der sogar in jedem Prozess auf dieselbe Weise abgebildet wird (um TLB-Flushing bei Syscall zu vermeiden, glaube ich). Und Dinge wie shmat ;) - sind das, was ich als "indirekten" Zugriff bezeichne. Man kann jedoch feststellen, dass sie normalerweise weit vom Prozesscode entfernt sind und wir normalerweise in der Lage sind, auf sie zuzugreifen (deshalb sind sie ja da, trotzdem führt ein unsachgemäßer Zugriff auf sie zu einem Segmentierungsfehler).
Ein Segmentierungsfehler kann jedoch auftreten, wenn auf den eigenen (Prozess-)Speicher auf unsachgemäße Weise zugegriffen wird (z. B. beim Versuch, in einen nicht beschreibbaren Bereich zu schreiben). Der häufigste Grund dafür ist jedoch der Zugriff auf den Teil des virtuellen Adressraums, der nicht abgebildet zu einer physischen überhaupt.
Und das alles in Bezug auf virtuelle Speichersysteme.
Ein Segmentierungsfehler wird durch eine Anforderung einer Seite verursacht, die der Prozess nicht in seiner Deskriptortabelle aufgeführt hat, oder durch eine ungültige Anforderung einer Seite, die er aufgeführt hat (z. B. eine Schreibanforderung für eine schreibgeschützte Seite).
Ein "Dangling Pointer" ist ein Zeiger, der auf eine gültige Seite zeigen kann oder auch nicht, aber auf ein "unerwartetes" Segment des Speichers zeigt.
Um ehrlich zu sein, wie andere Poster bereits erwähnt haben, hat Wikipedia einen sehr guten Artikel zu diesem Thema Schauen Sie also dort nach. Diese Art von Fehler ist sehr häufig und wird oft als Zugriffsverletzung oder allgemeiner Schutzfehler bezeichnet.
Das ist in C, C++ oder jeder anderen Sprache, die Zeiger zulässt, nicht anders. Diese Arten von Fehlern werden normalerweise durch Zeiger verursacht, die
- Wird verwendet, bevor er ordnungsgemäß initialisiert wurde
- Wird verwendet, nachdem der Speicher, auf den sie zeigen, neu zugewiesen oder gelöscht wurde.
- Wird in einem indizierten Array verwendet, bei dem der Index außerhalb der Array-Grenzen liegt. Dies ist in der Regel nur dann der Fall, wenn Sie Zeigermathematik mit traditionellen Arrays oder C-Strings durchführen, nicht mit STL-/Boost-basierten Sammlungen (in C++).
Según Wikipedia :
Ein Segmentierungsfehler tritt auf, wenn eine Programm versucht, auf eine Speicherstelle zuzugreifen Speicherplatz zuzugreifen, auf den es nicht zugreifen darf zugreifen darf, oder versucht, auf eine Speicherstelle Speicherplatz auf eine Weise zuzugreifen, die nicht erlaubt ist (z.B. der Versuch, auf eine schreibgeschützten Speicherplatz zu schreiben, oder einen Teil des Betriebssystems).
- See previous answers
- Weitere Antworten anzeigen