Грешка: „GDB не може да получи достъп до паметта на адрес“ в C++

Greska Gdb Ne Moze Da Poluci Dost P Do Pametta Na Adres V C



Отстраняването на грешки е съществена част от процеса при разработване на приложения на C++ или друг език за програмиране. Създаването на приложения в C++ не е лесно; това включва добри умения за структура на данни, умения за коригиране на грешки и управление на инструментите за отстраняване на грешки. GDB, GNU Debugger, е ефективен инструмент, който помага на разработчиците да идентифицират и разрешават грешките в своя код. GDB е интересно прост и полезен инструмент, който помага на разработчиците да открият и коригират грешките в кода.

Въпреки това, докато използвате GDB, може да срещнете грешката „грешка: GDB не може да получи достъп до паметта на адрес“. Тази грешка може да бъде объркваща и да затрудни продължаването на отстраняването на грешки. Тази статия е съсредоточена върху идентифицирането защо възниква тази грешка и разглежда някои примери за код, които ни помагат да разберем как да разрешим тази грешка.

Пример 1:

Нека видим нашия първи пример за код, който при изпълнение дава грешка „GDB не може да получи достъп до паметта на адрес“. Първо, разглеждаме кода. След това ще видим обяснението ред по ред.







#include
използвайки пространство от имена std ;
вътр основен ( невалиден ) {
вътр * стр ;
cout << * стр ;
}

Програмата започва с декларацията на “#include ” препроцесорна директива и използване на “namespace std”, които са от съществено значение да бъдат включени в програмата за използване на стандартните входни и изходни функции. След това идва основната входна точка, която е „int main(void);“. Този ред декларира началната точка на програмата.



В основната функция се декларира указателната променлива „*p“. Тук променливата 'p' не се инициализира. Следователно, той не сочи към конкретно място в паметта, което е запазено за цялото число. Този ред причинява грешка, която ще разрешим по-късно. В следващия ред се опитваме да отпечатаме стойността на променливата „*p“, използвайки израза „cout“.



Тъй като променливата „p“ е указател от тип integer, звездичката „*“ се използва за нейното дерефериране. Това означава, че стойността е в мястото на паметта, към което сочи. Въпреки това, тъй като указателят „p“ не е инициализиран и не сочи към конкретно и валидно местоположение, дереферирането на указателя ще доведе до недефинирано поведение. Следователно, това води до генериране на различни видове грешки в зависимост от системата и компилатора. Тъй като използваме GDB компилатора за отстраняване на грешки и изпълнение на тази програма, програмата за отстраняване на грешки ще изведе следната грешка. Грешката е показана в изходния фрагмент:





Както можете да видите в изхода, дебъгерът няма достъп до паметта. Тази програма дереферира неинициализиран указател, основната причина за това недефинирано поведение. Сега нека да видим как можем да разрешим този проблем. Правилният код е даден по-долу. Разгледайте го и ние ще ви обясним как коригираме грешката в кода:



#include
използвайки пространство от имена std ;
вътр основен ( невалиден ) {
вътр вал = 5 ;
вътр * стр = и вал ;
cout << 'Стойността е = ' << * стр ;

}

Както можете да видите, кодът е модифициран чрез включване на „int val =5;“ изявление. Този ред декларира целочислена променлива с име „val“ и я инициализира със стойност „5“. Следващият ред, “int *p = &val;”, декларира указателна променлива “*p” и се инициализира да сочи към адреса на променливата “val”. Преди това указателят „*p“ не сочеше към адрес на паметта, което причиняваше „не може да получи достъп до паметта на адрес 0x0“.

За да се реши този проблем, променливата „var“ се декларира, инициализира и присвоява на указателя „*p“. Сега указателят „*p“ сочи към адреса на променливата „val“, тъй като операторът „&“ взема адреса на „val“ и го присвоява на „p“. Отново изразът “cout” се използва за отпечатване на стойността на указателя “*p”. Вижте следния изходен фрагмент, за да видите стойността на „val“, която е достъпна от указателя „*p“:

Както можете да забележите, грешката е разрешена и стойността на „5“ е инициализирана, тъй като променливата „val“ е била отпечатана чрез извикване на указателя „*p“ valribale.

Пример 2:

Нека разгледаме друг пример, който обяснява как да се погрижим за грешката „GDB не може да получи достъп до паметта на адрес“ в програмата за код на C++. Кодът е даден по-долу за ваша справка. Погледни:

#include
вътр основен ( ) {
вътр * стр = нов вътр [ петнадесет ] ;
Изтрий [ ] стр ;
std :: cout << стр [ 2 ] << std :: endl ;
връщане 0 ;
}

Един от най-често срещаните сценарии, с които разработчиците се сблъскват, докато програмират с указатели, е неправилно или неправилно разпределение на паметта. GDB води до грешка всеки път, когато възникне неправилно разпределение и освобождаване на памет в C++ програма.

Имайки предвид предишния пример с код, указател “*p” се инициализира с нов int[15]. Този оператор динамично разпределя масив от 15 цели числа, използвайки оператора new. Променливата указател “*p” съхранява адреса на паметта на масива.

В следното изявление „delete[] p;,” заявява, че паметта е била освободена с помощта на командата delete[]. Командата delete[] освобождава предварително разпределената памет на указателя „*p“, което означава, че другата система, която използва, може отново да разпредели предварително разпределения блок памет. Когато се опитаме да отпечатаме стойността на променливата „*p“, използвайки израза „cout“, ще получим грешката при достъп до паметта, както се вижда в следния изход:

Нещата, които трябва да имате предвид тук е, че точното съобщение за грешка може леко да се различава в зависимост от вашата GDB версия и система. Но „грешката: GDB не може да получи достъп до паметта на местоположението“ и дадената грешка в предишния фрагмент са едни и същи. За да разрешим тази грешка, просто изместваме командата delete[] след оператора „cout“. Вижте модифицирания код в следното:

#include
вътр основен ( ) {
вътр * стр = нов вътр [ петнадесет ] ;
за ( вътр i = 0 ; i < петнадесет ; ++ i ) {
стр [ i ] = i * 2 - 5 + 8 ;
std :: cout << 'p[' << i << '] = ' << стр [ i ] << std :: endl ;
}
Изтрий [ ] стр ;
връщане 0 ;
}

Тук можете да видите, че инициализирахме масива със стойности, които се изчисляват по време на изпълнение, и отпечатваме всички стойности на цикъла с помощта на цикъла „for“. Най-важното нещо, което трябва да се отбележи тук, е изместването на командата delete[]; сега се извиква след получаване на всички стойности на масива, който е премахнал грешката при достъп до паметта. Вижте крайния изход на кода в следното:

Заключение

В заключение, грешката „грешка: GDB не може да получи достъп до паметта на адрес“ обикновено показва проблеми, свързани с паметта в C++ кода. Тази статия изследва някои често срещани сценарии, които инициират тази грешка, за да обясни кога и как тя може да бъде разрешена. Когато възникне тази грешка в кода, важно е внимателно да я прегледате, като обърнете голямо внимание на променливите на указателя, разпределението на паметта, масивите и структурите.

Освен това, функции като точки на прекъсване, които се предоставят от GDB, могат да помогнат при локализирането на грешката при отстраняване на грешки в програмата. Тези функции могат да помогнат при определяне на точното местоположение на грешки, свързани с паметта. Като адресират тези проблеми проактивно, разработчиците могат да подобрят стабилността и надеждността на своите C++ приложения.