logo

Segmentatiefout in C/C++

Segmentatiefouten in C of C++ is een fout die optreedt wanneer een programma probeert toegang te krijgen tot een geheugenlocatie waarvoor het geen toegangsrechten heeft. Deze fout treedt doorgaans op wanneer de geheugentoegang wordt geschonden en is een soort algemene beveiligingsfout. Segfouten zijn de afkorting voor segmentatiefouten.

De kern dump verwijst naar de registratie van de status van het programma, dat wil zeggen de bronnen in het geheugen en de processor. Het proberen toegang te krijgen tot niet-bestaand geheugen of geheugen dat door andere processen wordt gebruikt, veroorzaakt ook de segmentatiefout die tot een kerndump leidt.



Een programma heeft toegang tot specifieke geheugengebieden terwijl het actief is. Eerst wordt de stapel gebruikt om de lokale variabelen voor elke functie op te slaan. Bovendien kan er tijdens runtime geheugen aan worden toegewezen en op de heap worden opgeslagen (nieuw in C++ en je hoort het misschien ook wel de gratis winkel ). Het enige geheugen waartoe het programma toegang heeft, is zijn eigen geheugen (het eerder genoemde geheugen). Een segmentatiefout zal het gevolg zijn van elke toegang buiten die regio.

Segmentatiefout is een specifiek soort fout die wordt veroorzaakt door toegang tot het geheugen hoort niet bij jou :

  • Wanneer een stukje code een lees- en schrijfbewerking probeert uit te voeren op een alleen-lezen locatie in het geheugen of een vrijgemaakt geheugenblok, staat dit bekend als een segmentatiefout.
  • Het is een fout die wijst op geheugenbeschadiging.

Veelvoorkomende scenario's voor segmentatiefouten

Bij een segmentatiefout probeert een programma toegang te krijgen tot geheugen dat niet geautoriseerd is om toegang te krijgen, of dat niet bestaat. Enkele veelvoorkomende scenario's die segmentatiefouten kunnen veroorzaken zijn:



  1. Een letterlijke tekenreeks wijzigen
  2. Toegang krijgen tot een adres dat is vrijgegeven
  3. Toegang tot indexgrenzen buiten de array
  4. Onjuist gebruik van scanf()
  5. Stapeloverloop
  6. Dereferentie naar niet-geïnitialiseerde aanwijzer

1. Een letterlijke tekenreeks wijzigen

De letterlijke tekenreeksen worden opgeslagen in het alleen-lezen gedeelte van het geheugen. Dat is de reden waarom het onderstaande programma kan crashen (geeft een segmentatiefoutfout) omdat de regel *(str+1) = ‘n’ probeert een alleen-lezen geheugen te schrijven.

Voorbeeld:

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;> }>

>

>

Uitvoer

time-out: de bewaakte opdracht heeft de kern gedumpt

/bin/bash: regel 1: 32 Time-out voor segmentatiefout 15s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in

Raadpleeg Opslag voor tekenreeksen in C voor meer details.

2. Toegang krijgen tot een adres dat is vrijgegeven

Hier in de onderstaande code wordt de referentie p verwijderd na het vrijmaken van het geheugenblok, wat niet is toegestaan ​​door de compiler. Dergelijke pointers worden bungelende pointers genoemd en veroorzaken segmentfouten of abnormale programmabeëindiging tijdens runtime.

Voorbeeld:

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;> }>

waar vind ik mijn browserinstellingen

>

>

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;> }>

>

>

Uitvoer

Segmentation Fault>

3. Toegang tot de out-of-bounds array-index

In C en C++ kan toegang tot een array-index buiten het bereik een segmentatiefout of ander ongedefinieerd gedrag veroorzaken. Er is geen grenscontrole voor arrays in C en C++. Hoewel in C++ het gebruik van containers, zoals met de std::vector::at() methode of met een if() statement, out-of-bound fouten kan voorkomen.

Voorbeeld:

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;> }>

>

>

Uitvoer

Segmentation Faults>

4. Onjuist gebruik van scanf()

De functie scanf() verwacht het adres van een variabele als invoer. Hier in dit programma neemt n de waarde 2 aan en gaat ervan uit dat het adres 1000 is. Als we n doorgeven aan scanf(), wordt de invoer opgehaald uit STDIN in ongeldig geheugen 2 geplaatst, dat in plaats daarvan 1000 zou moeten zijn. Dit veroorzaakt geheugenbeschadiging, wat leidt tot een segmentatiefout.

Voorbeeld:

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;> }>

>

>

Uitvoer

Segementation Fault>

5. Stapeloverloop

Het is geen pointer-gerelateerd probleem, zelfs code heeft mogelijk geen enkele pointer. Dit komt doordat er onvoldoende geheugen op de stapel is. Het is ook een vorm van geheugenbeschadiging die kan optreden als gevolg van een grote arraygrootte, een groot aantal recursieve oproepen, veel lokale variabelen, enz.

Voorbeeld:

C




// 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;> }>

>

>

Uitvoer

Segmentation Fault>

6. Bufferoverloop

Als de gegevens die in de buffer worden opgeslagen groter zijn dan de toegewezen grootte van de buffer, treedt er een bufferoverloop op die tot de segmentatiefout leidt. De meeste methoden in de C-taal voeren geen grenscontrole uit, dus bufferoverflow komt vaak voor als we vergeten de vereiste grootte aan de buffer toe te wijzen.

Voorbeeld:

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;> }>

>

>

Uitvoer

Segmentation Fault>

7. Dereferentie naar een niet-geïnitialiseerde of NULL-aanwijzer

Het is een veel voorkomende programmeerfout om een ​​niet-geïnitialiseerde aanwijzer (wilde aanwijzer) te derefereren, wat kan resulteren in ongedefinieerd gedrag. Wanneer een pointer wordt gebruikt in een context die deze als een geldige pointer behandelt en toegang krijgt tot de onderliggende waarde ervan, ook al is deze niet geïnitialiseerd om naar een geldige geheugenlocatie te verwijzen, treedt deze fout op. Gegevensbeschadiging, programmafouten of segmentatiefouten kunnen hiervan het gevolg zijn. Afhankelijk van hun omgeving en staat bij het derefereren, kunnen niet-geïnitialiseerde pointers verschillende resultaten opleveren.

Zoals we weten, verwijst de NULL-aanwijzer niet naar een geheugenlocatie, dus zal het derefereren ervan resulteren in een segmentatiefout.

Voorbeeld:

C

inkapseling in Java




// 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;> }>

>

>

Uitvoer

Segmentation Fault>

Hoe segmentatiefouten op te lossen?

We kunnen segmentatiefouten oplossen door voorzichtig te zijn met de genoemde oorzaken:

  • Vermijd het wijzigen van letterlijke tekenreeksen.
  • Wees voorzichtig bij het gebruik van aanwijzingen, aangezien dit een van de meest voorkomende oorzaken is.
  • Houd rekening met de buffer- en stapelgrootte voordat u de gegevens opslaat om buffer- of stapeloverflow te voorkomen.
  • Controleren op grenzen voordat toegang wordt verkregen tot array-elementen.
  • Gebruik scanf() en printf() zorgvuldig om onjuiste formaatspecificaties of bufferoverloop te voorkomen.

Over het algemeen is de oorzaak van de segmentatiefout het verkrijgen van toegang tot het geheugen dat niet van u is in die ruimte. Zolang we dat vermijden, kunnen we de segmentatiefout vermijden. Als u de oorzaak van de fout niet kunt vinden, zelfs nadat u deze hebt uitgevoerd, is het raadzaam een ​​debugger te gebruiken, aangezien deze rechtstreeks naar het foutpunt in het programma leidt.