שגיאה: 'GDB לא יכול לגשת לזיכרון בכתובת' ב-C++

Sgy H Gdb L Ykwl Lgst Lzykrwn Bktwbt B C



איתור באגים הוא חלק חיוני בתהליך בעת פיתוח יישומים ב-C++ או בכל שפת תכנות אחרת. יצירת יישומים ב-C++ אינה קלה; זה כולל כישורי מבנה נתונים טובים, כישורי תיקון באגים וניהול כלי איתור באגים. ה-GDB, GNU Debugger, הוא כלי יעיל שעוזר למפתחים לזהות ולפתור את השגיאות בקוד שלהם. GDB הוא כלי מעניין פשוט ושימושי שעוזר למפתחים למצוא ולתקן את באגי הקוד.

עם זאת, בזמן השימוש ב-GDB, אתה עלול להיתקל בשגיאה 'שגיאה: GDB לא יכול לגשת לזיכרון בכתובת'. שגיאה זו עלולה להיות מבלבלת ומקשה על המשך ניפוי הבאגים. מאמר זה מתמקד בזיהוי מדוע שגיאה זו מתרחשת ובהסתכלות על כמה דוגמאות לקוד שעוזרות לנו להבין כיצד לפתור שגיאה זו.

דוגמה 1:

הבה נראה את דוגמה הקוד הראשונה שלנו, שעם ביצועה, נותנת שגיאה 'GDB לא יכול לגשת לזיכרון בכתובת'. ראשית, אנו מסתכלים על הקוד. לאחר מכן, נראה את ההסבר שורה אחר שורה של זה.







#include
באמצעות מרחב שמות סטד ;
int רָאשִׁי ( בָּטֵל ) {
int * ע ;
cout << * ע ;
}

התוכנית מתחילה בהצהרה של '#include ' הנחיית קדם-מעבד ושימוש ב-'namespace std' אשר חיוניים להיכלל בתוכנית כדי להשתמש בפונקציות הקלט והפלט הסטנדרטיות. לאחר מכן, מגיעה נקודת הכניסה הראשית שהיא 'int main(void);'. שורה זו מצהירה על נקודת ההתחלה של התוכנית.



בתוך הפונקציה הראשית, משתנה המצביע '*p' מוכרז. כאן, המשתנה 'p' אינו מאותחל. לפיכך, הוא אינו מצביע על מיקום זיכרון ספציפי כלשהו השמור למספר השלם. שורה זו גורמת לשגיאה שנפתור בהמשך. בשורה הבאה, אנו מנסים להדפיס את הערך של המשתנה '*p' באמצעות המשפט 'cout'.



מכיוון שהמשתנה 'p' הוא מצביע מסוג מספר שלם, הכוכבית '*' משמשת כדי להפנות אותו. המשמעות היא שהערך נמצא במיקום הזיכרון אליו הוא מצביע. עם זאת, מכיוון שמצביע ה-'p' לא אותחל ואינו מצביע על מיקום ספציפי ותקף כלשהו, ​​הרחקת המצביע תגרום להתנהגות לא מוגדרת. מכאן שהתוצאה היא יצירת שגיאות מסוגים שונים בהתאם למערכת ולמהדר. מכיוון שאנו משתמשים במהדר GDB כדי לאתר באגים ולהריץ את התוכנית הזו, מאתר הבאגים יזרוק את השגיאה הבאה. השגיאה מוצגת בקטע הפלט:





כפי שניתן לראות בפלט, מאתר הבאגים אינו יכול לגשת לזיכרון. תוכנית זו מפנה מצביע לא מאותחל, הסיבה העיקרית להתנהגות לא מוגדרת זו. עכשיו, בואו נראה איך אנחנו יכולים לפתור את הבעיה הזו. הקוד הנכון ניתן להלן. תסתכל על זה ונסביר איך אנחנו מתקנים את הבאג בקוד:



#include
באמצעות מרחב שמות סטד ;
int רָאשִׁי ( בָּטֵל ) {
int val = 5 ;
int * ע = & val ;
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
int רָאשִׁי ( ) {
int * ע = חָדָשׁ int [ חֲמֵשׁ עֶשׂרֵה ] ;
לִמְחוֹק [ ] ע ;
סטד :: cout << ע [ 2 ] << סטד :: endl ;
לַחֲזוֹר 0 ;
}

אחד התרחישים הנפוצים ביותר שהמפתחים נתקלים בהם בזמן תכנות עם מצביעים הוא הקצאת זיכרון שגויה או לא נכונה. ה-GDB גורם לשגיאה בכל פעם שמתרחשות הקצאת זיכרון וביטול הקצאה שגויים בתוכנית C++.

בהתחשב בדוגמה הקודמת של הקוד, מצביע '*p' מאותחל עם int חדש[15]. הצהרה זו מקצה באופן דינמי מערך של 15 מספרים שלמים באמצעות האופרטור החדש. משתנה המצביע '*p' מאחסן את כתובת הזיכרון של המערך.

בהצהרה הבאה, 'delete[] p;,' מציין שהזיכרון הוקצה באמצעות הפקודה delete[]. הפקודה delete[] מבטלת את הזיכרון שהוקצה קודם לכן של מצביע ה-'*p', מה שאומר שהמערכת האחרת שבה משתמשת יכולה להקצות שוב את בלוק הזיכרון שהוקצה קודם לכן. כאשר אנו מנסים להדפיס את הערך של המשתנה '*p' באמצעות המשפט 'cout', נקבל את שגיאת הגישה לזיכרון כפי שניתן לראות בפלט הבא:

הדברים שכדאי לזכור כאן הם שהודעת השגיאה המדויקת עשויה להיות שונה מעט בהתאם לגרסת ה-GDB ולמערכת שלך. אבל ה'שגיאה: GDB לא יכול לגשת לזיכרון במיקום' והשגיאה הנתונה בקטע הקודם זהים. כדי לפתור שגיאה זו, אנו פשוט מעבירים את הפקודה delete[] אחרי ההצהרה 'cout'. ראה את הקוד שהשתנה בקטע הבא:

#include
int רָאשִׁי ( ) {
int * ע = חָדָשׁ int [ חֲמֵשׁ עֶשׂרֵה ] ;
ל ( int אני = 0 ; אני < חֲמֵשׁ עֶשׂרֵה ; ++ אני ) {
ע [ אני ] = אני * 2 - 5 + 8 ;
סטד :: cout << 'p[' << אני << '] = ' << ע [ אני ] << סטד :: endl ;
}
לִמְחוֹק [ ] ע ;
לַחֲזוֹר 0 ;
}

כאן, אתה יכול לראות שאתחול המערך עם ערכים המחושבים בזמן הריצה, ואנחנו מדפיסים את כל הערכים של הלולאה באמצעות לולאת 'for'. הדבר החשוב ביותר שיש לציין כאן הוא הסטת ההצהרה delete[]; הוא נקרא כעת לאחר קבלת כל הערכים של המערך שהסיר את שגיאת הגישה לזיכרון. ראה את הפלט הסופי של הקוד בקטע הבא:

סיכום

לסיכום, השגיאה 'שגיאה: GDB לא יכול לגשת לזיכרון בכתובת' מציינת בדרך כלל בעיות הקשורות לזיכרון בקוד C++. מאמר זה בחן כמה תרחישים נפוצים שגורמים לשגיאה זו כדי להסביר מתי וכיצד ניתן לפתור אותה. כאשר שגיאה זו מתרחשת בקוד, חיוני לסקור אותו בקפידה על ידי תשומת לב רבה למשתני המצביע, הקצאות הזיכרון, המערכים והמבנים.

יתר על כן, תכונות כמו נקודות שבירה שמסופקות על ידי GDB יכולות לעזור באיתור השגיאה בזמן איתור באגים בתוכנית. תכונות אלה יכולות לעזור באיתור המיקום המדויק של שגיאות הקשורות לזיכרון. על ידי טיפול בבעיות אלו באופן יזום, המפתחים יכולים לשפר את היציבות והאמינות של יישומי C++ שלהם.