logo

Segmentierungsfehler in C/C++

Segmentierungsfehler in C oder C++ ist ein Fehler, der auftritt, wenn ein Programm versucht, auf einen Speicherort zuzugreifen, für den es keine Zugriffsberechtigung hat. Im Allgemeinen tritt dieser Fehler auf, wenn der Speicherzugriff verletzt wird, und ist eine Art allgemeiner Schutzfehler. Segfaults sind die Abkürzung für Segmentation Faults.

Der Core-Dump bezieht sich auf die Aufzeichnung des Zustands des Programms, also seiner Ressourcen in Speicher und Prozessor. Der Versuch, auf nicht vorhandenen Speicher oder Speicher zuzugreifen, der von anderen Prozessen verwendet wird, verursacht ebenfalls den Segmentierungsfehler, der zu einem Core-Dump führt.



Ein Programm hat während der Ausführung Zugriff auf bestimmte Speicherbereiche. Zunächst wird der Stapel verwendet, um die lokalen Variablen für jede Funktion zu speichern. Darüber hinaus wird möglicherweise zur Laufzeit Speicher zugewiesen und auf dem Heap gespeichert (neu in C++ und Sie hören es möglicherweise auch als „ kostenloser Laden ). Der einzige Speicher, auf den das Programm zugreifen darf, ist sein eigener (der zuvor erwähnte Speicher). Jeder Zugriff außerhalb dieser Region führt zu einem Segmentierungsfehler.

Ein Segmentierungsfehler ist eine bestimmte Art von Fehler, der durch den Zugriff auf den Speicher verursacht wird gehört nicht dir :

  • Wenn ein Codeteil versucht, einen Lese- und Schreibvorgang an einer schreibgeschützten Stelle im Speicher oder einem freigegebenen Speicherblock durchzuführen, spricht man von einem Segmentierungsfehler.
  • Es handelt sich um einen Fehler, der auf eine Speicherbeschädigung hinweist.

Häufige Segmentierungsfehlerszenarien

Bei einem Segmentierungsfehler versucht ein Programm, auf Speicher zuzugreifen, für den keine Zugriffsberechtigung besteht oder der nicht vorhanden ist. Einige häufige Szenarien, die Segmentierungsfehler verursachen können, sind:



  1. Ändern eines String-Literals
  2. Zugriff auf eine freigegebene Adresse
  3. Zugriff auf Indexgrenzen außerhalb des Arrays
  4. Unsachgemäße Verwendung von scanf()
  5. Paketüberfluss
  6. Dereferenzieren eines nicht initialisierten Zeigers

1. Ändern eines String-Literals

Die Zeichenfolgenliterale werden im schreibgeschützten Abschnitt des Speichers gespeichert. Aus diesem Grund kann das folgende Programm abstürzen (gibt einen Segmentierungsfehlerfehler aus), weil die Zeile *(str+1) = ‚n‘ versucht, einen Nur-Lese-Speicher zu schreiben.

Beispiel:

C






// C program to demonstrate segmentation fault> // by modifying a string literal> #include> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }>

>

>

C++




// C++ program to demonstrate segmentation fault> // by modifying a string literal> #include> using> namespace> std;> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }>

>

>

Ausgabe

Zeitüberschreitung: Der überwachte Befehl hat den Kern gedumpt

/bin/bash: Zeile 1: 32 Segmentierungsfehler-Timeout 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in

Weitere Einzelheiten finden Sie unter „Speicherung für Strings in C“.

2. Zugriff auf eine freigegebene Adresse

Hier im folgenden Code wird der Zeiger p dereferenziert, nachdem der Speicherblock freigegeben wurde, was vom Compiler nicht zugelassen wird. Solche Zeiger werden als baumelnde Zeiger bezeichnet und führen zur Laufzeit zu Segmentfehlern oder einem abnormalen Programmabbruch.

Beispiel:

C




// C program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> #include> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(8);> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// core dump/segmentation fault> >// as now this statement is illegal> >*p = 110;> >printf>(>'%d'>, *p);> >return> 0;> }>

zweidimensionales Array-Programm in c

>

>

C++




// C++ program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> using> namespace> std;> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(>sizeof>(>int>));> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// segmentation fault> >// as now this statement is illegal> >*p = 110;> >return> 0;> }>

>

>

Ausgabe

Segmentation Fault>

3. Zugriff auf den Array-Index außerhalb der Grenzen

In C und C++ kann der Zugriff auf einen Array-Index außerhalb der Grenzen einen Segmentierungsfehler oder anderes undefiniertes Verhalten verursachen. In C und C++ gibt es keine Grenzprüfung für Arrays. Obwohl in C++ die Verwendung von Containern, z. B. mit der Methode std::vector::at() oder mit einer if()-Anweisung, außerhalb der Grenzen liegende Fehler verhindern kann.

Beispiel:

C




// C program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> int> main(>void>)> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> (0);> }>

>

>

C++




// C++ program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> using> namespace> std;> int> main()> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> 0;> }>

>

>

Ausgabe

Segmentation Faults>

4. Unsachgemäße Verwendung von scanf()

Die Funktion scanf() erwartet als Eingabe die Adresse einer Variablen. Hier in diesem Programm nimmt n den Wert 2 an und geht davon aus, dass seine Adresse 1000 ist. Wenn wir n an scanf() übergeben, wird die von STDIN abgerufene Eingabe im ungültigen Speicher 2 abgelegt, der stattdessen 1000 sein sollte. Dies führt zu einer Speicherbeschädigung, die zu einem Segmentierungsfehler führt.

Beispiel:

C




// C program to demonstrate segmentation> // fault when value is passed to scanf> #include> int> main()> {> >int> n = 2;> >scanf>(>'%d'>, n);> >return> 0;> }>

>

>

C++




// C++ program to demonstrate segmentation> // fault when value is passed to scanf> #include> using> namespace> std;> int> main()> {> >int> n = 2;> >cin>> n;> >return> 0;> }>

>

>

Ausgabe

Segementation Fault>

5. Stapelüberlauf

Es handelt sich nicht um ein Zeigerproblem, auch wenn der Code möglicherweise keinen einzigen Zeiger hat. Das liegt daran, dass auf dem Stapel nicht mehr genügend Speicher vorhanden ist. Es handelt sich auch um eine Art Speicherbeschädigung, die aufgrund einer großen Array-Größe, einer großen Anzahl rekursiver Aufrufe, vieler lokaler Variablen usw. auftreten kann.

Beispiel:

C

Addierer voll




// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }>

>

>

C++




// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }>

>

>

Ausgabe

Segmentation Fault>

6. Pufferüberlauf

Wenn die im Puffer gespeicherten Daten größer sind als die zugewiesene Größe des Puffers, kommt es zu einem Pufferüberlauf, der zum Segmentierungsfehler führt. Die meisten Methoden in der Sprache C führen keine Begrenzungsprüfung durch, daher kommt es häufig zu einem Pufferüberlauf, wenn wir vergessen, dem Puffer die erforderliche Größe zuzuweisen.

Beispiel:

C




// C program to illustrate the> // segementation fault due to> // buffer overflow> #include> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }>

>

>

C++




// C++ program to illustrate the> // segementation fault due to> // buffer overflow> #include> using> namespace> std;> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }>

>

>

Ausgabe

Segmentation Fault>

7. Dereferenzierung eines nicht initialisierten oder NULL-Zeigers

Es ist ein häufiger Programmierfehler, einen nicht initialisierten Zeiger (Wild-Zeiger) zu dereferenzieren, was zu undefiniertem Verhalten führen kann. Wenn ein Zeiger in einem Kontext verwendet wird, der ihn als gültigen Zeiger behandelt und auf seinen zugrunde liegenden Wert zugreift, tritt dieser Fehler auf, obwohl er nicht so initialisiert wurde, dass er auf einen gültigen Speicherort zeigt. Dies kann zu Datenkorruption, Programmfehlern oder Segmentierungsfehlern führen. Abhängig von ihrer Umgebung und ihrem Zustand beim Dereferenzieren können nicht initialisierte Zeiger unterschiedliche Ergebnisse liefern.

Da wir wissen, dass der NULL-Zeiger auf keinen Speicherort zeigt, führt eine Dereferenzierung zu einem Segmentierungsfehler.

Beispiel:

C




// C program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >printf>(>'%d %d'>, *ptr, *nptr);> >return> 0;> }>

>

>

C++




// C++ program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> using> namespace> std;> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >cout << *ptr <<>' '> << *nptr;> >return> 0;> }>

>

>

Ausgabe

Segmentation Fault>

Wie können Segmentierungsfehler behoben werden?

Wir können Segmentierungsfehler beheben, indem wir auf die genannten Ursachen achten:

  • Vermeiden Sie es, Zeichenfolgenliterale zu ändern.
  • Seien Sie vorsichtig bei der Verwendung von Zeigern, da sie eine der häufigsten Ursachen sind.
  • Berücksichtigen Sie vor dem Speichern der Daten die Puffer- und Stapelgröße, um einen Puffer- oder Stapelüberlauf zu vermeiden.
  • Vor dem Zugriff auf Array-Elemente auf Grenzen prüfen.
  • Verwenden Sie scanf() und printf() sorgfältig, um falsche Formatspezifizierer oder Pufferüberlauf zu vermeiden.

Insgesamt ist die Ursache des Segmentierungsfehlers der Zugriff auf den Speicher in diesem Bereich, der Ihnen nicht gehört. Solange wir das vermeiden, können wir den Segmentierungsfehler vermeiden. Wenn Sie die Fehlerquelle auch danach nicht finden können, empfiehlt sich der Einsatz eines Debuggers, da dieser direkt zur Fehlerstelle im Programm führt.