logo

Chyba segmentácie v C/C++

Chyby segmentácie v C alebo C++ je chyba, ktorá sa vyskytuje, keď sa program pokúša získať prístup k miestu pamäte, ku ktorej nemá povolenie. Vo všeobecnosti sa táto chyba vyskytuje, keď je narušený prístup k pamäti a ide o typ všeobecnej chyby ochrany. Segfaults sú skratky pre segmentačné chyby.

The jadrová skládka sa týka zaznamenávania stavu programu, t.j. jeho zdrojov v pamäti a procesore. Pokus o prístup k neexistujúcej pamäti alebo pamäti, ktorú používajú iné procesy, tiež spôsobuje chybu segmentácie, ktorá vedie k výpisu jadra.



Program má počas behu prístup k špecifickým oblastiam pamäte. Po prvé, zásobník sa používa na uchovávanie lokálnych premenných pre každú funkciu. Okrem toho môže mať pamäť alokovanú za behu a uloženú na halde (nové v C++ a môžete tiež počuť, že sa nazýva voľný obchod ). Jediná pamäť, ku ktorej má program povolený prístup, je jeho vlastná (už spomínaná pamäť). Chyba segmentácie bude výsledkom akéhokoľvek prístupu mimo tohto regiónu.

Porucha segmentácie je špecifický druh chyby spôsobenej prístupom k pamäti, ktorá vám nepatrí :

  • Keď sa časť kódu pokúsi vykonať operáciu čítania a zápisu na mieste určenom len na čítanie v pamäti alebo uvoľnenom bloku pamäte, je to známe ako chyba segmentácie.
  • Je to chyba označujúca poškodenie pamäte.

Bežné scenáre porúch segmentácie

V prípade chyby segmentácie sa program pokúša o prístup k pamäti, ktorá nemá oprávnenie na prístup alebo ktorá neexistuje. Niektoré bežné scenáre, ktoré môžu spôsobiť chyby segmentácie, sú:



  1. Úprava reťazcového literálu
  2. Prístup k adrese, ktorá je uvoľnená
  3. Prístup k hraniciam indexu mimo poľa
  4. Nesprávne použitie funkcie scanf()
  5. Pretečenie zásobníka
  6. Dereferencovanie neinicializovaného ukazovateľa

1. Úprava reťazcového literálu

Reťazcové literály sú uložené v časti pamäte určenej len na čítanie. To je dôvod, prečo môže nižšie uvedený program zlyhať (zobrazuje chybu segmentácie), pretože riadok *(str+1) = „n“ sa pokúša zapísať pamäť len na čítanie.

Príklad:

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

>

>

Výkon

časový limit: monitorovaný príkaz vypustil jadro

/bin/bash: riadok 1: 32 Časový limit chyby segmentácie 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235in.

Ďalšie podrobnosti nájdete v časti Ukladanie reťazcov v jazyku C.

2. Prístup k adrese, ktorá je voľná

Tu v nižšie uvedenom kóde je ukazovateľ p dereferencovaný po uvoľnení bloku pamäte, čo kompilátor nepovoľuje. Takéto ukazovatele sa nazývajú visiace ukazovatele a spôsobujú chyby segmentov alebo abnormálne ukončenie programu za behu.

Príklad:

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

stiahnite si videá z youtube na vlc

>

>

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

>

>

Výkon

Segmentation Fault>

3. Prístup mimo rámec Array Index

V jazykoch C a C++ môže prístup k indexu poľa mimo hraníc spôsobiť chybu segmentácie alebo iné nedefinované správanie. Neexistuje žiadna kontrola hraníc pre polia v C a C++. Aj keď v C++, použitie kontajnerov, ako napríklad s metódou std::vector::at() alebo s príkazom if(), môže zabrániť chybám mimo rámec.

Príklad:

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

>

>

Výkon

Segmentation Faults>

4. Nesprávne použitie funkcie scanf()

Funkcia scanf() očakáva adresu premennej ako vstup. Tu v tomto programe n nadobudne hodnotu 2 a prevezme svoju adresu ako 1000. Ak odošleme n do scanf(), vstup získaný z STDIN sa umiestni do neplatnej pamäte 2, ktorá by mala byť namiesto toho 1000. To spôsobí poškodenie pamäte vedúce k chybe segmentácie.

Príklad:

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

>

>

Výkon

Segementation Fault>

5. Pretečenie zásobníka

Nejde o problém súvisiaci s ukazovateľom, aj keď kód nemusí mať jediný ukazovateľ. Je to kvôli nedostatku pamäte v zásobníku. Je to tiež typ poškodenia pamäte, ku ktorému môže dôjsť v dôsledku veľkej veľkosti poľa, veľkého počtu rekurzívnych volaní, množstva lokálnych premenných atď.

Príklad:

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

>

>

Výkon

Segmentation Fault>

6. Pretečenie vyrovnávacej pamäte

Ak sú údaje uložené vo vyrovnávacej pamäti väčšie ako alokovaná veľkosť vyrovnávacej pamäte, dôjde k pretečeniu vyrovnávacej pamäte, čo vedie k chybe segmentácie. Väčšina metód v jazyku C nevykonáva kontrolu viazanosti, takže k pretečeniu vyrovnávacej pamäte často dochádza, keď zabudneme prideliť vyrovnávacej pamäti požadovanú veľkosť.

Príklad:

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++

burak ozcivit




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

>

>

Výkon

Segmentation Fault>

7. Dereferencovanie neinicializovaného alebo NULL ukazovateľa

Bežnou chybou programovania je dereferencovanie neinicializovaného ukazovateľa ( wild pointer ), čo môže viesť k nedefinovanému správaniu. Keď sa ukazovateľ používa v kontexte, ktorý s ním zaobchádza ako s platným ukazovateľom a pristupuje k jeho základnej hodnote, aj keď nebol inicializovaný, aby ukazoval na platné miesto v pamäti, vyskytne sa táto chyba. Výsledkom môže byť poškodenie údajov, chyby programu alebo chyby segmentácie. V závislosti od prostredia a stavu pri dereferencovaní môžu neinicializované ukazovatele priniesť rôzne výsledky.

Ako vieme, ukazovateľ NULL neukazuje na žiadne miesto v pamäti, takže jeho dereferencovanie bude mať za následok chybu segmentácie.

Príklad:

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

>

>

Výkon

Segmentation Fault>

Ako opraviť chyby segmentácie?

Chyby segmentácie môžeme opraviť tak, že budeme dávať pozor na uvedené príčiny:

  • Vyhnite sa úpravám reťazcových literálov.
  • Buďte opatrní pri používaní ukazovateľov, pretože sú jednou z najčastejších príčin.
  • Pred uložením údajov zvážte veľkosť vyrovnávacej pamäte a zásobníka, aby ste sa vyhli pretečeniu vyrovnávacej pamäte alebo zásobníka.
  • Kontrola hraníc pred prístupom k prvkom poľa.
  • Používajte scanf() a printf() opatrne, aby ste sa vyhli nesprávnym špecifikátorom formátu alebo pretečeniu vyrovnávacej pamäte.

Celkovo je príčinou chyby segmentácie prístup k pamäti, ktorá vám v tomto priestore nepatrí. Pokiaľ sa tomu vyhneme, môžeme sa vyhnúť chybe segmentácie. Ak ani potom nemôžete nájsť zdroj chyby, odporúča sa použiť debugger, pretože priamo vedie k chybe v programe.