Viga: 'GDB ei pääse aadressile mälule juurde' keeles C++

Viga Gdb Ei Paase Aadressile Malule Juurde Keeles C



Silumine on C++ või mõnes muus programmeerimiskeeles rakenduste arendamisel protsessi oluline osa. Rakenduste loomine C++ keeles pole lihtne; see hõlmab häid andmestruktuurioskusi, vigade parandamise oskusi ja silumistööriistade haldamist. GDB, GNU silur, on tõhus tööriist, mis aitab arendajatel oma koodis olevaid vigu tuvastada ja lahendada. GDB on huvitavalt lihtne ja kasulik tööriist, mis aitab arendajatel koodivigu leida ja parandada.

Kuid GDB-d kasutades võite ilmneda tõrge 'viga: GDB ei pääse aadressil mälule juurde'. See viga võib tekitada segadust ja raskendada silumise jätkamist. See artikkel keskendub selle tõrke põhjuste väljaselgitamisele ja mõnele koodinäidetele, mis aitavad meil mõista, kuidas seda viga lahendada.

Näide 1:

Vaatame meie esimest koodinäidet, mis annab täitmisel veateate 'GDB ei pääse aadressil mälule juurde'. Esiteks vaatame koodi. Seejärel näeme selle rida-realt selgitust.







#include
kasutades nimeruum std ;
int peamine ( tühine ) {
int * lk ;
cout << * lk ;
}

Programm alustab eeltöötleja direktiivi '#include ' deklaratsiooniga ja 'namespace std' kasutamisega, mis on standardsete sisend- ja väljundfunktsioonide kasutamiseks programmi kaasatud. Pärast seda tuleb peamine sisenemispunkt, mis on 'int main(void);'. See rida deklareerib programmi alguspunkti.



Põhifunktsioonis deklareeritakse '*p' osuti muutuja. Siin muutujat 'p' ei lähtestata. Seega ei osuta see ühelegi kindlale mälukohale, mis on reserveeritud täisarvu jaoks. See rida põhjustab tõrke, mille lahendame hiljem. Järgmisel real proovime printida muutuja “*p” väärtuse, kasutades lauset “cout”.



Kuna muutuja 'p' on täisarvu tüüpi osuti, kasutatakse selle viitamiseks tärni '*'. See tähendab, et väärtus asub mälukohas, millele see osutab. Kuna aga „p” osutit ei lähtestatud ja see ei osuta ühelegi konkreetsele ja kehtivale asukohale, põhjustab kursori viitamise tühistamine määratlemata käitumist. Seega tekitab see olenevalt süsteemist ja kompilaatorist mitmesuguseid vigu. Kuna me kasutame selle programmi silumiseks ja käivitamiseks GDB kompilaatorit, annab silur järgmise vea. Viga kuvatakse väljundi väljavõttes:





Nagu väljundist näha, ei pääse silur mälule juurde. See programm eemaldab viited initsialiseerimata osutile, mis on selle määratlemata käitumise peamine põhjus. Nüüd vaatame, kuidas saame selle probleemi lahendada. Õige kood on toodud allpool. Vaadake seda ja me selgitame, kuidas koodis viga parandame:



#include
kasutades nimeruum std ;
int peamine ( tühine ) {
int val = 5 ;
int * lk = & val ;
cout << 'Väärtus on =' << * lk ;

}

Nagu näete, on koodi muudetud, lisades 'int val =5;' avaldus. See rida deklareerib täisarvulise muutuja nimega 'val' ja lähtestab selle väärtusega '5'. Järgmine rida 'int *p = &val;' deklareerib '*p' osutimuutuja ja lähtestatakse osutama muutuja 'val' aadressile. Varem ei osutanud '*p' osuti ühelegi mäluaadressile, mis põhjustas 'mälule juurdepääsu puudumisel aadressil 0x0'.

Selle probleemi lahendamiseks deklareeritakse muutuja 'var', lähtestatakse ja määratakse kursorile '*p'. Nüüd osutab kursor '*p' muutuja 'val' aadressile, kuna operaator '&' võtab 'val' aadressi ja määrab selle 'p'. Jällegi kasutatakse lauset 'cout' osuti '*p' väärtuse printimiseks. Vaadake järgmist väljundi fragmenti, et näha '*p' osutiga juurdepääsetava 'val' väärtust:

Nagu näete, on viga lahendatud ja väärtus '5' lähtestatakse, kuna muutuja 'val' on trükitud '*p' osuti valribale kutsumisega.

Näide 2:

Vaatleme veel ühte näidet, mis selgitab, kuidas toime tulla C++ koodiprogrammi veaga „GDB ei pääse aadressile mälule juurde”. Kood on toodud teile viitamiseks allpool. Vaata:

#include
int peamine ( ) {
int * lk = uus int [ viisteist ] ;
kustutada [ ] lk ;
std :: cout << lk [ 2 ] << std :: endl ;
tagasi 0 ;
}

Üks levinumaid stsenaariume, millega arendajad osutitega programmeerimisel kokku puutuvad, on vale või vale mälujaotus. GDB põhjustab tõrke alati, kui C++ programmis toimub vale mälujaotus ja -lahutus.

Arvestades eelmist koodinäidet, initsialiseeritakse “*p” osuti uue int-ga[15]. See avaldus eraldab uue operaatori abil dünaamiliselt 15 täisarvu massiivi. Osutimuutuja “*p” salvestab massiivi mäluaadressi.

Järgmises avalduses 'delete[] p;' ütleb, et mälu on vabastatud käsu delete[] abil. Käsk delete[] vabastab varem eraldatud '*p' osuti mälu, mis tähendab, et teised süsteemid saavad varem eraldatud mäluploki uuesti eraldada. Kui proovime printida muutuja “*p” väärtust lausega “cout”, saame mälule juurdepääsu vea, nagu on näha järgmises väljundis:

Siinkohal tasub meeles pidada, et täpne veateade võib sõltuvalt teie GDB versioonist ja süsteemist veidi erineda. Kuid 'viga: GDB ei pääse asukohas mälu juurde' ja eelmises katkendis antud viga on samad. Selle vea lahendamiseks nihutame lihtsalt käsu delete[] pärast lauset 'cout'. Vaadake muudetud koodi järgmiselt:

#include
int peamine ( ) {
int * lk = uus int [ viisteist ] ;
jaoks ( int i = 0 ; i < viisteist ; ++ i ) {
lk [ i ] = i * 2 - 5 + 8 ;
std :: cout << 'p[' << i << '] = ' << lk [ i ] << std :: endl ;
}
kustutada [ ] lk ;
tagasi 0 ;
}

Siin näete, et lähtestasime massiivi väärtustega, mis arvutatakse käitusajal, ja prindime kõik tsükli väärtused tsükli 'for' abil. Kõige tähtsam on siinkohal märkida delete[] lause nihutamine; seda kutsutakse nüüd pärast seda, kui on saadud kõik massiivi väärtused, mis on mälu juurdepääsu tõrke eemaldanud. Vaadake koodi lõplikku väljundit järgmiselt:

Järeldus

Kokkuvõtteks võib öelda, et viga 'viga: GDB ei pääse aadressil mälule juurde' viitab tavaliselt mäluga seotud probleemidele C++ koodis. Selles artiklis uuriti mõningaid levinumaid stsenaariume, mis selle vea käivitavad, et selgitada, millal ja kuidas seda saab lahendada. Kui see viga koodis ilmneb, on oluline see hoolikalt üle vaadata, pöörates erilist tähelepanu osuti muutujatele, mälueraldistele, massiividele ja struktuuridele.

Lisaks võivad GDB pakutavad funktsioonid, nagu katkestuspunktid, aidata programmi silumise ajal viga leida. Need funktsioonid aitavad määrata mäluga seotud vigade täpset asukohta. Nende probleemidega ennetavalt tegeledes saavad arendajad suurendada oma C++ rakenduste stabiilsust ja töökindlust.