logo

Segmentācijas kļūda C/C++

Segmentācijas kļūdas C vai C++ ir kļūda, kas rodas, kad programma mēģina piekļūt atmiņas vietai, kurai tai nav atļaujas piekļūt. Parasti šī kļūda rodas, ja tiek pārkāpta piekļuve atmiņai, un tā ir vispārējas aizsardzības kļūdas veids. Segfaults ir segmentācijas defektu saīsinājums.

The serdes izgāztuve attiecas uz programmas stāvokļa, t.i., tās resursu ierakstīšanu atmiņā un procesorā. Mēģinot piekļūt neesošai atmiņai vai atmiņai, ko izmanto citi procesi, rodas arī segmentācijas kļūda, kas izraisa kodola izgāztuves.



Programmai ir piekļuve noteiktiem atmiņas reģioniem, kamēr tā darbojas. Pirmkārt, kaudze tiek izmantota katras funkcijas vietējo mainīgo glabāšanai. Turklāt tai var būt atmiņa, kas ir piešķirta izpildes laikā un saglabāta kaudzē (jauna C++ valodā, un jūs varat arī dzirdēt to sauc par bezmaksas veikals ). Vienīgā atmiņa, kurai programmai ir atļauts piekļūt, ir tās pašas atmiņa (iepriekš minētā atmiņa). Segmentācijas kļūme radīsies no jebkuras piekļuves ārpus šī reģiona.

Segmentācijas kļūme ir īpaša veida kļūda, ko izraisa piekļuve atmiņai nepieder tev :

  • Ja koda fragments mēģina veikt lasīšanas un rakstīšanas darbību tikai lasāmā vietā atmiņā vai atbrīvotajā atmiņas blokā, to sauc par segmentācijas kļūdu.
  • Tā ir kļūda, kas norāda uz atmiņas bojājumu.

Bieži sastopami segmentācijas kļūdu scenāriji

Segmentācijas kļūmes gadījumā programma mēģina piekļūt atmiņai, kurai nav atļauts piekļūt vai kura neeksistē. Daži izplatīti scenāriji, kas var izraisīt segmentācijas kļūdas, ir šādi:



  1. Virknes literāļa modificēšana
  2. Piekļuve adresei, kas ir atbrīvota
  3. Piekļuve ārpus masīva indeksa robežām
  4. Nepareiza scanf() izmantošana
  5. Stack Overflow
  6. Atsauces no inicializēta rādītāja atcelšana

1. String Literal modificēšana

Virknes literāļi tiek saglabāti atmiņas tikai lasāmajā sadaļā. Tāpēc tālāk redzamā programma var avarēt (sniedz segmentācijas kļūdas kļūdu), jo rinda *(str+1) = 'n' mēģina ierakstīt tikai lasāmatmiņu.

Piemērs:

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

>

>

Izvade

taimauts: uzraudzītā komanda izmeta kodolu

/bin/bash: 1. rindiņa: 32. Segmentācijas kļūdas taimauts 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.

Sīkāku informāciju skatiet sadaļā Virkņu glabāšana valodā C.

2. Piekļuve atbrīvotai adresei

Šeit zemāk esošajā kodā rādītājs p tiek noņemts pēc atmiņas bloka atbrīvošanas, ko kompilators neatļauj. Šādas norādes tiek sauktas par nokareniem rādītājiem, un tās izpildes laikā rada segmenta kļūdas vai neparastu programmas pārtraukšanu.

Piemērs:

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

pārvērst virkni interger

>

>

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

>

>

Izvade

Segmentation Fault>

3. Piekļuve ārpus robežām masīva indeksam

Programmā C un C++, piekļūstot ārpus robežām masīva indeksam, var rasties segmentācijas kļūda vai cita nenoteikta darbība. C un C++ masīviem nav robežu pārbaudes. Lai gan C++, konteineru izmantošana, piemēram, ar std::vector::at() metodi vai ar if() priekšrakstu, var novērst ārpussaistes kļūdas.

Piemērs:

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

>

>

Izvade

Segmentation Faults>

4. Nepareiza scanf() izmantošana

Funkcija scanf() sagaida mainīgā adresi kā ievadi. Šajā programmā n ņem vērtību 2 un pieņem, ka tās adrese ir 1000. Ja mēs nododam n uz scanf(), no STDIN iegūtā ievade tiek ievietota nederīgā 2. atmiņā, kuras vietā jābūt 1000. Tas izraisa atmiņas bojājumus, kas izraisa segmentācijas kļūdu.

Piemērs:

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

>

>

Izvade

Segementation Fault>

5. Stack Overflow

Tā nav ar rādītāju saistīta problēma, pat kodam var nebūt neviena rādītāja. Tas ir tāpēc, ka kaudzē beidzas atmiņa. Tas ir arī atmiņas bojājuma veids, kas var rasties liela masīva lieluma, liela skaita rekursīvu zvanu, daudzu vietējo mainīgo utt. dēļ.

Piemērs:

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

>

>

Izvade

Segmentation Fault>

6. Bufera pārpilde

Ja buferī glabātie dati ir lielāki par bufera piešķirto lielumu, notiek bufera pārpilde, kas izraisa segmentācijas kļūdu. Lielākā daļa C valodas metožu neveic saistošo pārbaudi, tāpēc bufera pārpilde notiek bieži, kad mēs aizmirstam buferim piešķirt nepieciešamo izmēru.

Piemērs:

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

>

>

kas ir izņēmumu apstrāde java

Izvade

Segmentation Fault>

7. Atsauces atcelšana uz neinicializētu vai NULL rādītāju

Tā ir izplatīta programmēšanas kļūda, atceļot atsauci uz neinicializētu rādītāju (savvaļas rādītāju), kas var izraisīt nedefinētu darbību. Ja rādītājs tiek izmantots kontekstā, kurā tas tiek uzskatīts par derīgu rādītāju un piekļūst tā pamatā esošajai vērtībai, pat ja tas nav inicializēts, lai norādītu uz derīgu atmiņas vietu, rodas šī kļūda. Tas var izraisīt datu bojājumus, programmas kļūdas vai segmentācijas kļūdas. Atkarībā no vides un stāvokļa, kad tiek atceltas atsauces, neinicializēti rādītāji var dot dažādus rezultātus.

Kā mēs zinām, NULL rādītājs nenorāda uz nevienu atmiņas vietu, tāpēc atsauces atcelšana radīs segmentācijas kļūdu.

Piemērs:

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

>

>

Izvade

Segmentation Fault>

Kā novērst segmentācijas kļūdas?

Mēs varam novērst segmentācijas kļūdas, rūpīgi ievērojot minētos cēloņus:

  • Izvairieties no virkņu literāļu modificēšanas.
  • Esiet piesardzīgs, lietojot norādes, jo tās ir viens no visbiežāk sastopamajiem iemesliem.
  • Pirms datu saglabāšanas ņemiet vērā bufera un steka lielumu, lai izvairītos no bufera vai steka pārpildes.
  • Robežu pārbaude pirms piekļuves masīva elementiem.
  • Izmantojiet scanf() un printf() uzmanīgi, lai izvairītos no nepareiziem formāta parametriem vai bufera pārpildes.

Kopumā segmentācijas kļūdas iemesls ir piekļuve atmiņai, kas jums nepieder šajā vietā. Kamēr mēs to nedarīsim, mēs varam izvairīties no segmentācijas kļūdas. Ja nevarat atrast kļūdas avotu pat pēc tās izdarīšanas, ieteicams izmantot atkļūdotāju, jo tas tieši noved pie kļūdas punkta programmā.