Klaida: „GDB negali pasiekti atminties adresu“ C++

Klaida Gdb Negali Pasiekti Atminties Adresu C



Derinimas yra esminė proceso dalis kuriant programas C++ ar bet kuria kita programavimo kalba. Sukurti programas C++ nėra lengva; Tai apima gerus duomenų struktūros įgūdžius, klaidų taisymo įgūdžius ir derinimo įrankių valdymą. GDB, GNU Debugger, yra efektyvus įrankis, padedantis kūrėjams nustatyti ir išspręsti savo kodo klaidas. GDB yra įdomiai paprastas ir naudingas įrankis, padedantis kūrėjams rasti ir ištaisyti kodo klaidas.

Tačiau naudodami GDB galite susidurti su klaida „klaida: GDB negali pasiekti atminties adresu“. Ši klaida gali sukelti painiavą ir apsunkinti nuolatinį derinimo procesą. Šiame straipsnyje siekiama nustatyti, kodėl įvyksta ši klaida, ir pažvelgti į keletą kodų pavyzdžių, kurie padeda suprasti, kaip išspręsti šią klaidą.

1 pavyzdys:

Pažiūrėkime savo pirmąjį kodo pavyzdį, kuris vykdymo metu pateikia klaidą „GDB negali pasiekti atminties adresu“. Pirmiausia žiūrime į kodą. Tada pamatysime eilutę po eilutės paaiškinimą.







#include
naudojant vardų erdvė std ;
tarpt pagrindinis ( tuštuma ) {
tarpt * p ;
cout << * p ;
}

Programa pradedama deklaruojant „#include “ išankstinio procesoriaus direktyvą ir naudojant „namespace std“, kurios yra būtinos norint įtraukti į programą, norint naudoti standartines įvesties ir išvesties funkcijas. Po to ateina pagrindinis įvesties taškas, kuris yra „int main(void);“. Ši eilutė nurodo programos pradžios tašką.



Pagrindinėje funkcijoje yra deklaruojamas „*p“ žymeklio kintamasis. Čia „p“ kintamasis nėra inicijuojamas. Taigi jis nenurodo jokios konkrečios atminties vietos, rezervuotos sveikajam skaičiui. Ši eilutė sukelia klaidą, kurią išspręsime vėliau. Kitoje eilutėje bandome atspausdinti „*p“ kintamojo reikšmę naudodami „cout“ teiginį.



Kadangi „p“ kintamasis yra sveikojo skaičiaus rodyklė, jo nuorodai panaikinti naudojama žvaigždutė „*“. Tai reiškia, kad reikšmė yra toje atminties vietoje, į kurią ji nurodo. Tačiau kadangi „p“ žymeklis nebuvo inicijuotas ir nenurodo į jokią konkrečią ir galiojančią vietą, rodyklės nuorodos panaikinimas lems neapibrėžtą elgesį. Taigi, priklausomai nuo sistemos ir kompiliatoriaus, generuojamos įvairios klaidos. Kadangi mes naudojame GDB kompiliatorių šiai programai derinti ir paleisti, derintuvas išmes šią klaidą. Klaida rodoma išvesties fragmente:





Kaip matote išvestyje, derinimo priemonė negali pasiekti atminties. Ši programa panaikina nuorodų į inicijuotą rodyklę, kuri yra pagrindinė tokio neapibrėžto elgesio priežastis. Dabar pažiūrėkime, kaip galime išspręsti šią problemą. Teisingas kodas pateikiamas toliau. Pažvelkite į tai ir mes paaiškinsime, kaip ištaisome klaidą kode:



#include
naudojant vardų erdvė std ;
tarpt pagrindinis ( tuštuma ) {
tarpt val = 5 ;
tarpt * p = & val ;
cout << 'Vertė yra =' << * p ;

}

Kaip matote, kodas modifikuojamas įtraukiant „int val = 5;“ pareiškimas. Ši eilutė deklaruoja sveikąjį kintamąjį, pavadintą „val“, ir inicijuoja jį reikšme „5“. Kita eilutė „int *p = &val;“ deklaruoja „*p“ rodyklės kintamąjį ir inicijuojama, kad būtų nurodyta „val“ kintamojo adresą. Anksčiau „*p“ rodyklė nenurodė jokio atminties adreso, dėl kurio „negalima pasiekti atminties adresu 0x0“.

Norint išspręsti šią problemą, kintamasis „var“ deklaruojamas, inicijuojamas ir priskiriamas „*p“ žymekliui. Dabar „*p“ rodyklė nurodo „val“ kintamojo adresą, nes „&“ operatorius paima „val“ adresą ir priskiria jį „p“. Vėlgi, teiginys „cout“ naudojamas „*p“ rodyklės reikšmei spausdinti. Žr. šį išvesties fragmentą, kad pamatytumėte „val“ reikšmę, pasiekiamą naudojant „*p“ žymeklį:

Kaip matote, klaida buvo išspręsta ir „5“ reikšmė inicijuojama, nes „val“ kintamasis buvo išspausdintas iškviečiant „*p“ rodyklę valribale.

2 pavyzdys:

Panagrinėkime kitą pavyzdį, paaiškinantį, kaip C++ kodo programoje pašalinti klaidą „GDB negali pasiekti atminties adresu“. Kodas pateikiamas toliau, kad galėtumėte susipažinti. Pažvelk:

#include
tarpt pagrindinis ( ) {
tarpt * p = naujas tarpt [ penkiolika ] ;
Ištrinti [ ] p ;
std :: cout << p [ 2 ] << std :: endl ;
grąžinti 0 ;
}

Vienas iš dažniausiai pasitaikančių scenarijų, su kuriais susiduria kūrėjai programuodami su rodyklėmis, yra neteisingas arba netinkamas atminties paskirstymas. GDB sukelia klaidą, kai C++ programoje įvyksta neteisingas atminties paskirstymas ir atskyrimas.

Atsižvelgiant į ankstesnį kodo pavyzdį, „*p“ rodyklė inicijuojama naudojant naują int[15]. Šis teiginys dinamiškai priskiria 15 sveikųjų skaičių masyvą naudojant naują operatorių. Rodyklės kintamasis „*p“ saugo masyvo atminties adresą.

Toliau pateiktame teiginyje „delete[] p;“ nurodoma, kad atmintis buvo atlaisvinta naudojant komandą delete[]. Komanda delete[] atlaisvina anksčiau skirtą „*p“ rodyklės atmintį, o tai reiškia, kad kitos sistemos gali vėl paskirstyti anksčiau skirtą atminties bloką. Kai bandysime atspausdinti „*p“ kintamojo reikšmę naudodami „cout“ teiginį, gausime prieigos prie atminties klaidą, kaip parodyta šioje išvestyje:

Čia reikia atsiminti, kad tikslus klaidos pranešimas gali šiek tiek skirtis priklausomai nuo jūsų GDB versijos ir sistemos. Tačiau „klaida: GDB negali pasiekti atminties toje vietoje“ ir nurodyta klaida ankstesniame fragmente yra ta pati. Norėdami išspręsti šią klaidą, tiesiog perkeliame komandą delete[] po teiginio „cout“. Pakeistą kodą žiūrėkite toliau pateiktame skyriuje:

#include
tarpt pagrindinis ( ) {
tarpt * p = naujas tarpt [ penkiolika ] ;
dėl ( tarpt i = 0 ; i < penkiolika ; ++ i ) {
p [ i ] = i * 2 - 5 + 8 ;
std :: cout << 'p[' << i << '] = ' << p [ i ] << std :: endl ;
}
Ištrinti [ ] p ;
grąžinti 0 ;
}

Čia matote, kad inicijavome masyvą su reikšmėmis, kurios apskaičiuojamos vykdymo metu, ir spausdiname visas ciklo reikšmes naudodami kilpą „for“. Svarbiausias dalykas, į kurį reikia atkreipti dėmesį, yra trynimo[] teiginio perkėlimas; dabar jis iškviečiamas gavus visas masyvo, kuris pašalino prieigos prie atminties klaidą, reikšmes. Žiūrėkite galutinę kodo išvestį toliau pateiktoje knygoje:

Išvada

Apibendrinant, klaida „klaida: GDB negali pasiekti atminties adresu“ paprastai rodo su atmintimi susijusias problemas C++ kode. Šiame straipsnyje buvo nagrinėjami keli įprasti scenarijai, dėl kurių atsiranda ši klaida, siekiant paaiškinti, kada ir kaip ją galima išspręsti. Kai kode įvyksta ši klaida, būtina atidžiai jį peržiūrėti, ypatingą dėmesį skiriant rodyklės kintamiesiems, atminties paskirstymui, masyvams ir struktūroms.

Be to, tokios funkcijos kaip lūžio taškai, kurias teikia GDB, gali padėti nustatyti klaidą derinant programą. Šios funkcijos gali padėti tiksliai nustatyti su atmintimi susijusių klaidų vietą. Aktyviai spręsdami šias problemas, kūrėjai gali padidinti savo C++ programų stabilumą ir patikimumą.