Segmenteringsfel i C eller C++ är ett fel som uppstår när ett program försöker komma åt en minnesplats som det inte har behörighet att komma åt. I allmänhet uppstår detta fel när minnesåtkomsten kränks och är en typ av allmänt skyddsfel. Segfaults är förkortningen för segmenteringsfel.
De kärndumpning hänvisar till inspelningen av programmets tillstånd, dvs dess resurser i minne och processor. Att försöka komma åt obefintligt minne eller minne som används av andra processer orsakar också segmenteringsfelet som leder till en kärndump.
Ett program har tillgång till specifika minnesområden medan det körs. Först används stacken för att hålla de lokala variablerna för varje funktion. Dessutom kan det ha minne tilldelat vid körning och sparat på högen (ny i C++ och du kan också höra att det kallas gratis butik ). Det enda minne som programmet har tillåtelse att komma åt är det eget (minnet som nämnts tidigare). Ett segmenteringsfel kommer att uppstå från all åtkomst utanför den regionen.
Segmenteringsfel är en specifik typ av fel som orsakas av att komma åt minne som tillhör inte dig :
- När en kodbit försöker göra en läs-och-skrivoperation på en skrivskyddad plats i minnet eller ett frigjort minnesblock, kallas det ett segmenteringsfel.
- Det är ett fel som indikerar minnesskada.
Vanliga scenarier för segmenteringsfel
I ett segmenteringsfel försöker ett program komma åt minne som inte är behörigt att komma åt eller som inte finns. Några vanliga scenarier som kan orsaka segmenteringsfel är:
- Ändra en bokstavlig sträng
- Åtkomst till en adress som är fri
- Åtkomst till out-of-array-indexgränser
- Felaktig användning av scanf()
- Stack Overflow
- Avreferenser oinitierad pekare
1. Ändra en sträng bokstavlig
Strängliteralerna lagras i den skrivskyddade delen av minnet. Det är därför programmet nedan kan krascha (ger segmenteringsfel) eftersom raden *(str+1) = 'n' försöker skriva ett skrivskyddat minne.
Exempel:
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;> }> |
>
>
Produktion
timeout: det övervakade kommandot dumpade kärnan
/bin/bash: rad 1: 32 Segmenteringsfel timeout 15s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb59344235.in.in.
Se Lagring för strängar i C för mer information.
2. Åtkomst till en frigjord adress
Här i koden nedan, dereferenseras pekaren p efter att minnesblocket frigjorts, vilket inte är tillåtet av kompilatorn. Sådana pekare kallas dinglande pekare och de producerar segmentfel eller onormal programavslutning vid körning.
Exempel:
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;> }> |
git status -s
>
>
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;> }> |
>
>
Produktion
Segmentation Fault>
3. Åtkomst till out-of-bounds Array Index
I C och C++ kan tillgång till ett out-of-bounds-arrayindex orsaka ett segmenteringsfel eller annat odefinierat beteende. Det finns ingen gränskontroll för arrayer i C och C++. Även om det är i C++ kan användningen av behållare som med metoden std::vector::at() eller med en if()-sats förhindra out-of-bound-fel.
Exempel:
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;> }> |
>
>
Produktion
Segmentation Faults>
4. Felaktig användning av scanf()
Funktionen scanf() förväntar sig adressen till en variabel som indata. Här i detta program tar n värdet 2 och antar sin adress som 1000. Om vi skickar n till scanf() placeras indata hämtad från STDIN i ogiltigt minne 2 som istället borde vara 1000. Detta orsakar minneskorruption som leder till ett segmenteringsfel.
Exempel:
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;> }> |
>
>
Produktion
Segementation Fault>
5. Stackoverflow
Det är inte ett pekarerelaterat problem, även om koden kanske inte har en enda pekare. Det beror på att minnet i stacken är slut. Det är också en typ av minneskorruption som kan hända på grund av stor arraystorlek, ett stort antal rekursiva anrop, massor av lokala variabler, etc.
Exempel:
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;> }> |
>
>
Produktion
Segmentation Fault>
6. Buffertspill
Om data som lagras i bufferten är större än buffertens tilldelade storlek uppstår ett buffertspill som leder till segmenteringsfelet. De flesta av metoderna i C-språket utför inte bunden kontroll, så buffertspill inträffar ofta när vi glömmer att tilldela bufferten den önskade storleken.
Exempel:
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;> }> |
>
>
Produktion
Segmentation Fault>
7. Avhänvisning till en oinitierad eller NULL-pekare
Det är ett vanligt programmeringsfel att avreferera en oinitierad pekare (vildpekare), vilket kan resultera i odefinierat beteende. När en pekare används i ett sammanhang som behandlar den som en giltig pekare och får åtkomst till dess underliggande värde, även om den inte har initierats för att peka på en giltig minnesplats, uppstår detta fel. Datakorruption, programfel eller segmenteringsfel kan bli resultatet av detta. Beroende på deras miljö och tillstånd när de refererar, kan oinitierade pekare ge olika resultat.
Som vi vet pekar NULL-pekaren inte på någon minnesplats, så om man refererar den kommer det att resultera i ett segmenteringsfel.
Exempel:
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;> }> |
>
>
Produktion
java parseint
Segmentation Fault>
Hur åtgärdar man segmenteringsfel?
Vi kan åtgärda segmenteringsfel genom att vara försiktiga med de nämnda orsakerna:
- Undvik att ändra strängbokstavar.
- Var försiktig när du använder pekare eftersom de är en av de vanligaste orsakerna.
- Tänk på bufferten och stackstorleken innan du lagrar data för att undvika buffert eller stackspill.
- Kontrollera för gränser innan du kommer åt matriselement.
- Använd scanf() och printf() noggrant för att undvika felaktiga formatspecifikationer eller buffertspill.
Sammantaget är orsaken till segmenteringsfelet att komma åt minnet som inte tillhör dig i det utrymmet. Så länge vi undviker att göra det kan vi undvika segmenteringsfelet. Om du inte kan hitta källan till felet även efter att ha gjort det, rekommenderas det att använda en debugger eftersom det direkt leder till felpunkten i programmet.