it-swarm.com.de

Was ist ein Segmentierungsfehler?

Was ist ein Segmentierungsfehler? Ist es anders in C und C++? Wie hängen Segmentierungsfehler und baumelnde Zeiger zusammen?

518
Rajendra Uppal

Ein Segmentierungsfehler ist eine bestimmte Art von Fehler, der durch den Zugriff auf Speicher verursacht wird, der "Ihnen nicht gehört". Dies ist ein Hilfsmechanismus, der Sie davon abhält, den Speicher zu beschädigen und schwer zu debuggende Speicherfehler einzuführen. Immer wenn Sie einen Seg-Fehler bekommen, wissen Sie, dass Sie etwas mit dem Speicher falsch gemacht haben - Zugriff auf eine bereits freigegebene Variable, Schreiben in einen schreibgeschützten Teil des Speichers usw. Der Segmentierungsfehler ist in den meisten Sprachen, mit denen Sie sich herumschlagen, im Wesentlichen derselbe 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 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 nicht mehr existiert, wie hier:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

Der Zeiger p baumelt, weil er auf die Zeichenvariable c zeigt, die nach dem Blockende nicht mehr existiert. Und wenn Sie versuchen, den baumelnden Zeiger zu dereferenzieren (wie *p='A'), erhalten Sie wahrscheinlich einen Segfault.

605
zoul

Es sollte beachtet werden, dass ein Segmentierungsfehler nicht durch direkten Zugriff auf einen anderen Prozessspeicher verursacht wird (das höre ich manchmal), da dies einfach nicht möglich ist. Mit virtuellem Speicher verfügt jeder Prozess über einen 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 physische Adressraum (möglicherweise) unterschiedlichen virtuellen Adressen zugeordnet ist, und der Kernel-Speicher, der sogar in jedem Prozess auf die gleiche Weise zugeordnet wird (um TLB-Flushing bei syscall zu vermeiden, denke ich). Und Dinge wie shmat;) - das zähle ich als "indirekten" Zugang. Man kann jedoch überprüfen, ob sie sich in der Regel weit vom Prozesscode entfernt befinden und wir in der Regel auf sie zugreifen können (aus diesem Grund sind sie dort, doch ein unsachgemäßer Zugriff führt zu Segmentierungsfehlern).

Ein Segmentierungsfehler kann jedoch auftreten, wenn auf unseren eigenen (Prozess-) Speicher nicht ordnungsgemäß zugegriffen wird (z. B. versucht wird, 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 zugeordnet physisch ist.

Und das alles in Bezug auf virtuelle Speichersysteme.

105

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 einen sehr guten Artikel zu diesem Thema . Diese Art von Fehler ist sehr verbreitet und wird oft auch als "andere Dinge" bezeichnet, z. B. "Zugriffsverletzung" oder Allgemeine Schutzverletzung.

Sie unterscheiden sich nicht in C, C++ oder einer anderen Sprache, die Zeiger zulässt. Diese Art von Fehlern wird normalerweise durch Zeiger verursacht

  1. Wird vor der ordnungsgemäßen Initialisierung verwendet
  2. Wird verwendet, nachdem der Speicher, auf den sie zeigen, neu zugewiesen oder gelöscht wurde.
  3. Wird in einem indizierten Array verwendet, in dem sich der Index außerhalb der Array-Grenzen befindet. Dies ist im Allgemeinen nur dann der Fall, wenn Sie Zeigermathematik für herkömmliche Arrays oder C-Strings ausführen, nicht für STL/Boost-basierte Auflistungen (in C++).
27
Component 10

Laut Wikipedia:

Ein Segmentierungsfehler tritt auf, wenn ein Programm versucht, auf einen Speicherort zuzugreifen, auf den es nicht zugreifen darf, oder wenn versucht wird, auf einen Speicherort auf nicht zulässige Weise zuzugreifen (z. B. beim Versuch, an einen schreibgeschützten Speicherort zu schreiben, oder einen Teil des Betriebssystems zu überschreiben).

15
Orhan Cinar

Ein Segmentierungsfehler wird auch durch Hardwarefehler verursacht, in diesem Fall durch die RAM Speicher. Dies ist die seltenere Ursache, aber wenn Sie in Ihrem Code keinen Fehler finden, kann ein Memtest hilfreich sein.

Die Lösung in diesem Fall ändern Sie den RAM.

bearbeiten:

Hier gibt es eine Referenz: Segmentierungsfehler nach Hardware

11
Alejo Bernardin

Segmentierungsfehler tritt auf, wenn ein Prozess (laufende Instanz eines Programms) versucht, auf eine Nur-Lese-Speicheradresse oder einen Speicherbereich zuzugreifen, der von einem anderen Prozess verwendet wird, oder auf die nicht vorhandene (ungültige) Speicheradresse . 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
7
Sohail xIN3N

Die Seite Segmentation_fault von Wikipedia enthält eine sehr gute Beschreibung, in der nur die Ursachen und Gründe aufgeführt sind. Werfen Sie einen Blick in das Wiki, um eine detaillierte Beschreibung zu erhalten.

Bei der Datenverarbeitung ist ein Segmentierungsfehler (häufig als "Segfault" bezeichnet) 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:

  • Dereferenzieren von NULL-Zeigern - dies ist durch Speicherverwaltungshardware besonders gekennzeichnet
  • Versuch, auf eine nicht vorhandene Speicheradresse (außerhalb des Adressraums des Prozesses) zuzugreifen
  • Beim Versuch, auf den Speicher zuzugreifen, hat das Programm keine Rechte (z. B. Kernelstrukturen im Prozesskontext).
  • Schreibzugriff auf Nur-Lese-Speicher (z. B. Codesegment)

Diese werden häufig durch Programmierfehler verursacht, die zu ungültigen Speicherzugriffen 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 freigegebenen/freigegebenen/gelöschten Speicher verweist)

  • Ein Pufferüberlauf.

  • Ein Stapelüberlauf.

  • Versuch, ein Programm auszuführen, das nicht korrekt kompiliert wurde. (Einige Compiler geben trotz Kompilierungsfehlern eine ausführbare Datei aus.)

5
Roy

Mit einfachen Worten: Ein Segmentierungsfehler ist das Betriebssystem, das ein Signal an das Programm sendet, das besagt, dass es einen unzulässigen Speicherzugriff erkannt hat und das Programm vorzeitig beendet, um eine Beschädigung des Speichers zu verhindern.

4
FilipeCanatto

Ein Segmentierungsfehler oder eine Zugriffsverletzung tritt auf, wenn ein Programm versucht, auf einen nicht vorhandenen Speicherort oder auf einen nicht zulässigen 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, daher tritt Segfault auf.

rsachen 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).
1
Mohit Rohilla

Es gibt mehrere gute Erklärungen für "Segmentierungsfehler" in den Antworten, aber da es bei Segmentierungsfehlern häufig zu einem Speicherauszug des Speicherinhalts kommt, wollte ich die Beziehung zwischen dem Teil "core dumped" in Segmentierungsfehler (Core Dumped) und Speicher stammen 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.

Entnommen aus hier .

1
Viktor Nonov

"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 int main sein (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 bei der Übergabe an printf in ein Double umgewandelt wird), sollten Sie den Formatbezeichner% f verwenden. Der Formatbezeichner% s ist für Zeichenfolgen (Zeichenfelder mit '\ 0'-Endung).

1
PHP Worm...