Napake segmentacije v C ali C++ je napaka, ki se pojavi, ko program poskuša dostopati do pomnilniške lokacije, za dostop do katere nima dovoljenja. Na splošno se ta napaka pojavi, ko je moten dostop do pomnilnika in je vrsta splošne napake zaščite. Segfaults so okrajšave za segmentacijske napake.
The odlagališče jedra se nanaša na beleženje stanja programa, to je njegovih virov v pomnilniku in procesorju. Poskus dostopa do neobstoječega pomnilnika ali pomnilnika, ki ga uporabljajo drugi procesi, povzroči tudi napako segmentacije, ki povzroči izpis jedra.
Program ima med izvajanjem dostop do določenih območij pomnilnika. Najprej se sklad uporablja za shranjevanje lokalnih spremenljivk za vsako funkcijo. Poleg tega ima lahko med izvajanjem dodeljen pomnilnik in shranjen na kopici (novo v C++ in morda boste slišali, da se imenuje brezplačna trgovina ). Edini pomnilnik, do katerega lahko program dostopa, je njegov lastni (prej omenjeni pomnilnik). Napaka segmentacije bo posledica kakršnega koli dostopa zunaj te regije.
Napaka segmentacije je posebna vrsta napake, ki jo povzroči dostop do pomnilnika ne pripada tebi :
- Ko del kode poskuša izvesti operacijo branja in pisanja na lokaciji samo za branje v pomnilniku ali osvobojenem bloku pomnilnika, je to znano kot napaka segmentacije.
- To je napaka, ki kaže na poškodbo pomnilnika.
Pogosti scenariji napak pri segmentaciji
Pri napaki segmentacije poskuša program dostopati do pomnilnika, ki nima dovoljenja za dostop ali pa ne obstaja. Nekateri pogosti scenariji, ki lahko povzročijo napake pri segmentaciji, so:
- Spreminjanje nizovnega literala
- Dostop do naslova, ki je sproščen
- Dostop do meja indeksa zunaj polja
- Nepravilna uporaba scanf()
- Preobremenitev
- Dereferenciranje neinicializiranega kazalca
1. Spreminjanje nizovnega dobeseda
Nizovni literali so shranjeni v delu pomnilnika samo za branje. Zato se lahko spodnji program zruši (pove napako pri segmentaciji), ker vrstica *(str+1) = 'n' poskuša zapisati v pomnilnik samo za branje.
primer:
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;> }> |
>
>
Izhod
časovna omejitev: nadzorovani ukaz je vrgel jedro
/bin/bash: vrstica 1: 32 Časovna omejitev napake segmentacije 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in
Za več podrobnosti glejte Shramba za nize v C.
2. Dostop do naslova, ki je osvobojen
Tukaj v spodnji kodi je kazalec p dereferenciran po sprostitvi pomnilniškega bloka, česar prevajalnik ne dovoljuje. Takšni kazalci se imenujejo viseči kazalci in povzročajo napake segmentov ali nenormalno prekinitev programa med izvajanjem.
primer:
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;> }> |
nadzorovano strojno učenje
>
>
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;> }> |
>
>
Izhod
Segmentation Fault>
3. Dostop do Indeksa polja zunaj meja
V C in C++ lahko dostop do indeksa polja zunaj meja povzroči napako segmentacije ali drugo nedefinirano vedenje. V C in C++ ni preverjanja meja za polja. Čeprav v C++ uporaba vsebnikov, na primer z metodo std::vector::at() ali s stavkom if(), lahko prepreči napake izven meja.
primer:
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;> }> |
>
>
Izhod
Segmentation Faults>
4. Nepravilna uporaba scanf()
Funkcija scanf() pričakuje naslov spremenljivke kot vhod. Tukaj v tem programu n sprejme vrednost 2 in privzame svoj naslov kot 1000. Če posredujemo n v scanf(), se vhod, pridobljen iz STDIN, postavi v neveljaven pomnilnik 2, ki bi moral biti namesto tega 1000. To povzroči okvaro pomnilnika, ki povzroči napako segmentacije.
primer:
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;> }> |
>
>
Izhod
Segementation Fault>
5. Stack Overflow
To ni problem, povezan s kazalcem, celo koda morda nima enega samega kazalca. To je zaradi zmanjkanja pomnilnika na skladu. To je tudi vrsta poškodbe pomnilnika, do katere lahko pride zaradi velike velikosti polja, velikega števila rekurzivnih klicev, veliko lokalnih spremenljivk itd.
primer:
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;> }> |
>
>
Izhod
Segmentation Fault>
6. Prekoračitev medpomnilnika
Če so podatki, shranjeni v medpomnilniku, večji od dodeljene velikosti medpomnilnika, pride do prekoračitve medpomnilnika, kar povzroči napako segmentacije. Večina metod v jeziku C ne izvaja vezanega preverjanja, zato se pogosto zgodi prelivanje medpomnilnika, ko pozabimo dodeliti zahtevano velikost medpomnilnika.
primer:
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++
shreya ghoshal
// 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;> }> |
>
>
Izhod
Segmentation Fault>
7. Dereferenciranje neinicializiranega ali NULL kazalca
Pogosta programska napaka je dereferenciranje neinicializiranega kazalca (divji kazalec), kar lahko povzroči nedefinirano vedenje. Ko se kazalec uporablja v kontekstu, ki ga obravnava kot veljaven kazalec in dostopa do njegove osnovne vrednosti, čeprav ni bil inicializiran, da kaže na veljavno pomnilniško lokacijo, pride do te napake. Posledica tega so lahko poškodbe podatkov, programske napake ali napake pri segmentaciji. Odvisno od okolja in stanja pri dereferenciranju lahko neinicializirani kazalci dajo različne rezultate.
Kot vemo, kazalec NULL ne kaže na nobeno pomnilniško lokacijo, zato bo dereferenciranje povzročilo napako segmentacije.
primer:
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;> }> |
>
>
Izhod
Segmentation Fault>
Kako odpraviti napake pri segmentaciji?
Napake segmentacije lahko odpravimo tako, da smo pozorni na navedene vzroke:
- Izogibajte se spreminjanju literalov nizov.
- Bodite previdni pri uporabi kazalcev, saj so eden najpogostejših vzrokov.
- Pred shranjevanjem podatkov upoštevajte velikost medpomnilnika in sklada, da se izognete prelivanju medpomnilnika ali sklada.
- Preverjanje meja pred dostopom do elementov polja.
- Previdno uporabljajte scanf() in printf(), da se izognete nepravilnim specifikatorjem formata ali prekoračitvi medpomnilnika.
Na splošno je vzrok za napako segmentacije dostop do pomnilnika, ki vam v tem prostoru ne pripada. Dokler se temu izogibamo, se lahko izognemo napaki segmentacije. Če ne morete najti vira napake tudi potem, ko to storite, je priporočljivo uporabiti razhroščevalnik, saj vodi neposredno do točke napake v programu.