ข้อผิดพลาด: “GDB ไม่สามารถเข้าถึงหน่วยความจำตามที่อยู่” ใน C ++

Khx Phid Phlad Gdb Mi Samarth Khea Thung Hnwy Khwam Ca Tam Thi Xyu Ni C



การดีบักเป็นส่วนสำคัญของกระบวนการในการพัฒนาแอปพลิเคชันในภาษา C++ หรือภาษาการเขียนโปรแกรมอื่นๆ การสร้างแอปพลิเคชันในภาษา C++ ไม่ใช่เรื่องง่าย มันเกี่ยวข้องกับทักษะโครงสร้างข้อมูลที่ดี ทักษะการแก้ไขข้อบกพร่อง และการจัดการเครื่องมือแก้ไขข้อบกพร่อง GDB หรือ GNU Debugger เป็นเครื่องมือที่มีประสิทธิภาพที่ช่วยให้นักพัฒนาสามารถระบุและแก้ไขข้อผิดพลาดในโค้ดของตนได้ GDB เป็นเครื่องมือที่เรียบง่ายและมีประโยชน์ที่น่าสนใจซึ่งช่วยให้นักพัฒนาสามารถค้นหาและแก้ไขข้อบกพร่องของโค้ดได้

อย่างไรก็ตาม ขณะใช้ GDB คุณอาจพบข้อผิดพลาด “ข้อผิดพลาด: GDB ไม่สามารถเข้าถึงหน่วยความจำตามที่อยู่” ข้อผิดพลาด ข้อผิดพลาดนี้อาจทำให้เกิดความสับสนและทำให้ยากต่อการดีบักต่อไป บทความนี้มุ่งเน้นไปที่การระบุสาเหตุที่เกิดข้อผิดพลาดนี้และดูตัวอย่างโค้ดบางส่วนที่ช่วยให้เราเข้าใจวิธีแก้ไขข้อผิดพลาดนี้

ตัวอย่างที่ 1:

ให้เราดูตัวอย่างโค้ดแรกของเราที่มีข้อผิดพลาด “GDB ไม่สามารถเข้าถึงหน่วยความจำตามที่อยู่” เมื่อดำเนินการ ก่อนอื่นเรามาดูโค้ดกันก่อน จากนั้นเราจะเห็นคำอธิบายทีละบรรทัด







#รวม
โดยใช้ เนมสเปซ มาตรฐาน ;
ภายใน หลัก ( เป็นโมฆะ ) {
ภายใน * พี ;
ศาล << * พี ;
}

โปรแกรมเริ่มต้นด้วยการประกาศคำสั่งตัวประมวลผลล่วงหน้า “#include ” และใช้ “namespace std” ซึ่งจำเป็นที่จะรวมไว้ในโปรแกรมเพื่อใช้ฟังก์ชันอินพุตและเอาต์พุตมาตรฐาน หลังจากนั้น จุดเริ่มต้นหลักจะมาซึ่งก็คือ “int main(void);” บรรทัดนี้ประกาศจุดเริ่มต้นของโปรแกรม



ภายในฟังก์ชันหลัก จะมีการประกาศตัวแปรตัวชี้ “*p” ในที่นี้ ตัวแปร “p” ไม่ได้ถูกเตรียมใช้งาน ดังนั้นจึงไม่ได้ชี้ไปยังตำแหน่งหน่วยความจำเฉพาะใดๆ ที่สงวนไว้สำหรับจำนวนเต็ม บรรทัดนี้ทำให้เกิดข้อผิดพลาดซึ่งเราจะแก้ไขในภายหลัง ในบรรทัดถัดไป เราพยายามพิมพ์ค่าของตัวแปร “*p” โดยใช้คำสั่ง “cout”



เนื่องจากตัวแปร “p” เป็นตัวชี้ประเภทจำนวนเต็ม จึงมีการใช้เครื่องหมายดอกจัน “*” ในการอ้างอิง ซึ่งหมายความว่าค่าอยู่ที่ตำแหน่งหน่วยความจำที่ชี้ไป อย่างไรก็ตาม เนื่องจากตัวชี้ 'p' ไม่ได้เตรียมใช้งานและไม่ได้ชี้ไปยังตำแหน่งที่เฉพาะเจาะจงและถูกต้อง การยกเลิกการอ้างอิงตัวชี้จะส่งผลให้เกิดการทำงานที่ไม่ได้กำหนดไว้ ดังนั้นจึงส่งผลให้เกิดข้อผิดพลาดหลายประเภทขึ้นอยู่กับระบบและคอมไพเลอร์ เนื่องจากเราใช้คอมไพเลอร์ GDB เพื่อดีบักและรันโปรแกรมนี้ ตัวดีบักเกอร์จะแสดงข้อผิดพลาดต่อไปนี้ ข้อผิดพลาดแสดงอยู่ในตัวอย่างเอาต์พุต:





ดังที่คุณเห็นในเอาต์พุต ดีบักเกอร์ไม่สามารถเข้าถึงหน่วยความจำได้ โปรแกรมนี้ยกเลิกการอ้างอิงตัวชี้ที่ไม่ได้เตรียมใช้งาน ซึ่งเป็นสาเหตุหลักของพฤติกรรมที่ไม่ได้กำหนดไว้นี้ ตอนนี้เรามาดูกันว่าเราจะแก้ไขปัญหานี้ได้อย่างไร รหัสที่ถูกต้องได้รับดังต่อไปนี้ ลองดูที่มันแล้วเราจะอธิบายวิธีการแก้ไขข้อบกพร่องในโค้ด:



#รวม
โดยใช้ เนมสเปซ มาตรฐาน ;
ภายใน หลัก ( เป็นโมฆะ ) {
ภายใน วาล = 5 ;
ภายใน * พี = & วาล ;
ศาล << “ค่าคือ =” << * พี ;

}

อย่างที่คุณเห็น โค้ดได้รับการแก้ไขโดยการรวม “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 ++ รหัสได้รับดังต่อไปนี้สำหรับการอ้างอิงของคุณ ลองดูสิ:

#รวม
ภายใน หลัก ( ) {
ภายใน * พี = ใหม่ ภายใน [ สิบห้า ] ;
ลบ [ ] พี ;
มาตรฐาน :: ศาล << พี [ 2 ] << มาตรฐาน :: สิ้นสุด ;
กลับ 0 ;
}

หนึ่งในสถานการณ์ทั่วไปที่นักพัฒนาพบขณะเขียนโปรแกรมด้วยพอยน์เตอร์นั้นไม่ถูกต้องหรือจัดสรรหน่วยความจำไม่เหมาะสม GDB ส่งผลให้เกิดข้อผิดพลาดทุกครั้งที่มีการจัดสรรหน่วยความจำที่ไม่ถูกต้องและการจัดสรรคืนเกิดขึ้นในโปรแกรม C ++

เมื่อพิจารณาจากตัวอย่างโค้ดก่อนหน้านี้ ตัวชี้ “*p” จะเริ่มต้นด้วย int[15] ใหม่ คำสั่งนี้จะจัดสรรอาร์เรย์จำนวนเต็ม 15 จำนวนแบบไดนามิกโดยใช้ตัวดำเนินการใหม่ ตัวแปรตัวชี้ “*p” จะจัดเก็บที่อยู่หน่วยความจำของอาเรย์

ในข้อความต่อไปนี้ “delete[] p;,” ระบุว่าหน่วยความจำได้รับการจัดสรรคืนโดยใช้คำสั่ง Delete[] คำสั่ง Delete[] จะจัดสรรหน่วยความจำที่จัดสรรไว้ก่อนหน้านี้ของตัวชี้ “*p” ซึ่งหมายความว่าระบบอื่นที่ใช้สามารถจัดสรรบล็อกหน่วยความจำที่จัดสรรไว้ก่อนหน้านี้ได้อีกครั้ง เมื่อเราพยายามพิมพ์ค่าของตัวแปร “*p” โดยใช้คำสั่ง “cout” เราจะได้รับข้อผิดพลาดในการเข้าถึงหน่วยความจำดังที่เห็นในผลลัพธ์ต่อไปนี้:

สิ่งที่ควรจำไว้คือข้อความแสดงข้อผิดพลาดอาจแตกต่างกันเล็กน้อยขึ้นอยู่กับเวอร์ชันและระบบ GDB ของคุณ แต่ 'ข้อผิดพลาด: GDB ไม่สามารถเข้าถึงหน่วยความจำที่ตำแหน่งนั้น' และข้อผิดพลาดที่ระบุในตัวอย่างก่อนหน้าจะเหมือนกัน เพื่อแก้ไขข้อผิดพลาดนี้ เราเพียงแค่เปลี่ยนคำสั่ง Delete[] หลังคำสั่ง 'cout' ดูรหัสที่แก้ไขดังต่อไปนี้:

#รวม
ภายใน หลัก ( ) {
ภายใน * พี = ใหม่ ภายใน [ สิบห้า ] ;
สำหรับ ( ภายใน ฉัน = 0 ; ฉัน < สิบห้า ; ++ ฉัน ) {
พี [ ฉัน ] = ฉัน * 2 - - 5 + 8 ;
มาตรฐาน :: ศาล << 'พ[' << ฉัน << '] = ' << พี [ ฉัน ] << มาตรฐาน :: สิ้นสุด ;
}
ลบ [ ] พี ;
กลับ 0 ;
}

ที่นี่ คุณจะเห็นว่าเราเริ่มต้นอาร์เรย์ด้วยค่าที่คำนวณ ณ รันไทม์ และเราพิมพ์ค่าทั้งหมดของลูปโดยใช้ลูป 'for' สิ่งสำคัญที่สุดที่ควรทราบที่นี่คือการเปลี่ยนคำสั่ง Delete[]; ตอนนี้ถูกเรียกหลังจากได้รับค่าทั้งหมดของอาร์เรย์ที่ได้ลบข้อผิดพลาดในการเข้าถึงหน่วยความจำแล้ว ดูผลลัพธ์สุดท้ายของโค้ดดังต่อไปนี้:

บทสรุป

โดยสรุป ข้อผิดพลาด “ข้อผิดพลาด: GDB ไม่สามารถเข้าถึงหน่วยความจำตามที่อยู่” มักจะบ่งชี้ถึงปัญหาที่เกี่ยวข้องกับหน่วยความจำในโค้ด C++ บทความนี้สำรวจสถานการณ์ทั่วไปบางประการที่ทำให้เกิดข้อผิดพลาดนี้เพื่ออธิบายว่าจะสามารถแก้ไขได้เมื่อใดและอย่างไร เมื่อข้อผิดพลาดนี้เกิดขึ้นในโค้ด จำเป็นต้องตรวจสอบอย่างรอบคอบโดยให้ความสำคัญกับตัวแปรตัวชี้ การจัดสรรหน่วยความจำ อาร์เรย์ และโครงสร้างอย่างใกล้ชิด

นอกจากนี้ คุณลักษณะเช่นเบรกพอยต์ที่ GDB จัดเตรียมไว้สามารถช่วยในการค้นหาข้อผิดพลาดขณะทำการดีบักโปรแกรม คุณสมบัติเหล่านี้สามารถช่วยระบุตำแหน่งที่แน่นอนของข้อผิดพลาดเกี่ยวกับหน่วยความจำได้ ด้วยการแก้ไขปัญหาเหล่านี้ในเชิงรุก นักพัฒนาสามารถเพิ่มความเสถียรและความน่าเชื่อถือของแอปพลิเคชัน C++ ของตนได้