C:n segmentointivirheet tai C++ on virhe, joka ilmenee, kun ohjelma yrittää päästä muistipaikkaan, johon sillä ei ole käyttöoikeutta. Yleensä tämä virhe ilmenee, kun muistiin pääsyä rikotaan, ja se on eräänlainen yleinen suojausvirhe. Segfaults ovat lyhenne sanoista segmentointivirheet.
The ydin kaatopaikka tarkoittaa ohjelman tilan eli sen resurssien tallentamista muistiin ja prosessoriin. Yrittäminen käyttää olematonta muistia tai muistia, jota muut prosessit käyttävät, aiheuttaa myös segmentointivian, joka johtaa ydinvedostilaan.
Ohjelmalla on pääsy tiettyihin muistialueisiin sen ollessa käynnissä. Ensinnäkin pinoa käytetään pitämään kunkin funktion paikalliset muuttujat. Lisäksi sillä voi olla ajonaikaisesti varattu muistia ja tallennettu kasaan (uusi C++:ssa ja saatat myös kuulla sen nimellä ilmainen kauppa ). Ainoa muisti, jota ohjelmalla on oikeus käyttää, on se oma (aiemmin mainittu muisti). Segmentointivirhe johtuu kaikista pääsystä kyseisen alueen ulkopuolella.
Segmentointivika on erityinen virhe, jonka aiheuttaa pääsy muistiin ei kuulu sinulle :
- Kun koodinpala yrittää tehdä luku- ja kirjoitustoimintoa vain luku -tilassa muistissa tai vapautetussa muistilohkossa, sitä kutsutaan segmentointivirheeksi.
- Se on virhe, joka ilmaisee muistin vioittumisen.
Yleiset segmentointivirheskenaariot
Segmentointivirheessä ohjelma yrittää käyttää muistia, jota ei ole valtuutettu käyttämään tai jota ei ole olemassa. Joitakin yleisiä skenaarioita, jotka voivat aiheuttaa segmentointivirheitä, ovat:
- Merkkijonoliteraalin muokkaaminen
- Pääsy osoitteeseen, joka on vapautettu
- Pääsy taulukon ulkopuolisiin hakemistorajoihin
- scanf()-funktion virheellinen käyttö
- Pinon ylivuoto
- Peruutetaan alustamaton osoitin
1. Merkkijonoliteraalin muokkaaminen
Merkkijonoliteraalit tallennetaan muistin vain luku -osioon. Tästä syystä alla oleva ohjelma saattaa kaatua (antaa segmentointivirheen), koska rivi *(str+1) = 'n' yrittää kirjoittaa vain lukumuistia.
Esimerkki:
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;> }> |
>
>
Lähtö
aikakatkaisu: valvottu komento tyhjensi ytimen
/bin/bash: rivi 1: 32 Segmentointivian aikakatkaisu 15s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.
Katso lisätietoja C:n merkkijonojen varastoinnista.
2. Vapautetun osoitteen käyttäminen
Tässä alla olevassa koodissa osoitin p puretaan muistilohkon vapauttamisen jälkeen, mitä kääntäjä ei salli. Tällaisia osoittimia kutsutaan roikkuviksi osoittimiksi ja ne aiheuttavat segmenttivirheitä tai epänormaalia ohjelman päättymistä ajon aikana.
Esimerkki:
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;> }> |
täysi muoto pvr
>
>
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;> }> |
>
>
Lähtö
Segmentation Fault>
3. Rajojen ulkopuolisen Array Indexin käyttäminen
C:ssä ja C++:ssa rajojen ulkopuolisen taulukkoindeksin käyttö voi aiheuttaa segmentointivirheen tai muun määrittelemättömän toiminnan. C:ssä ja C++:ssa ei ole taulukoiden rajatarkistusta. Vaikka C++:ssa säilöjen käyttö, kuten std::vector::at()-metodin tai if()-käskyn kanssa, voi estää ulkopuoliset virheet.
Esimerkki:
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;> }> |
>
>
Lähtö
Segmentation Faults>
4. Scanf()-funktion virheellinen käyttö
Scanf()-funktio odottaa muuttujan osoitteen syötteenä. Tässä ohjelmassa n ottaa arvon 2 ja olettaa sen osoitteeksi 1000. Jos välitämme n:lle scanf(), STDIN:stä haettu syöte sijoitetaan virheelliseen muistiin 2, jonka pitäisi olla 1000. Tämä aiheuttaa muistin vioittumista, mikä johtaa segmentointivirheeseen.
Esimerkki:
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;> }> |
>
>
Lähtö
Segementation Fault>
5. Pinon ylivuoto
Se ei ole osoittimeen liittyvä ongelma, vaikka koodissa ei ehkä ole yhtä osoitinta. Se johtuu pinon muistin loppumisesta. Se on myös eräänlainen muistin korruptio, joka voi johtua suuresta taulukon koosta, suuresta määrästä rekursiivisia kutsuja, paljon paikallisia muuttujia jne.
Esimerkki:
C
// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }> |
>
bourne-ain -kuori
>
C++
// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }> |
>
>
Lähtö
Segmentation Fault>
6. Puskurin ylivuoto
Jos puskuriin tallennettava data on suurempi kuin puskurille varattu koko, tapahtuu puskurin ylivuoto, joka johtaa segmentointivirheeseen. Suurin osa C-kielen menetelmistä ei suorita sidottua tarkistusta, joten puskurin ylivuoto tapahtuu usein, kun unohdamme varata vaaditun koon puskurille.
Esimerkki:
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;> }> |
>
>
Lähtö
Segmentation Fault>
7. Viittauksen poistaminen alustamattomasta tai NULL-osoittimesta
On yleinen ohjelmointivirhe poistaa viittaukset alustamattomaan osoittimeen (villi osoitin), mikä voi johtaa määrittelemättömään toimintaan. Kun osoitinta käytetään kontekstissa, joka käsittelee sitä kelvollisena osoittimena ja käyttää sen taustalla olevaa arvoa, vaikka sitä ei ole alustettu osoittamaan kelvolliseen muistipaikkaan, tämä virhe ilmenee. Tästä voi seurata tietojen vioittumista, ohjelmavirheitä tai segmentointivirheitä. Alustamattomat osoittimet voivat tuottaa erilaisia tuloksia ympäristöstään ja viittauksen poiston tilasta riippuen.
Kuten tiedämme, NULL-osoitin ei osoita mihinkään muistipaikkaan, joten sen viittauksen purkaminen johtaa segmentointivirheeseen.
Esimerkki:
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;> }> |
>
>
Lähtö
Segmentation Fault>
Kuinka korjata segmentointivirheet?
Voimme korjata segmentointivirheet olemalla varovaisia mainituista syistä:
- Vältä merkkijonoliteraalien muokkaamista.
- Ole varovainen käyttäessäsi osoittimia, koska ne ovat yksi yleisimmistä syistä.
- Puskurin ja pinon koko on otettava huomioon ennen tietojen tallentamista puskurin tai pinon ylivuodon välttämiseksi.
- Rajausten tarkistaminen ennen taulukon elementtien käyttöä.
- Käytä scanf()- ja printf()-koodeja varovasti välttääksesi vääriä muotomäärityksiä tai puskurin ylivuotoa.
Kaiken kaikkiaan segmentointivian syynä on pääsy muistiin, joka ei kuulu sinulle kyseisessä tilassa. Niin kauan kuin vältämme tekemästä sitä, voimme välttää segmentointivirheen. Jos et löydä virheen lähdettä sen jälkeenkään, on suositeltavaa käyttää debuggeria, koska se johtaa suoraan ohjelman virhepisteeseen.