GDB - คู่มือฉบับย่อ
ดีบักเกอร์คือโปรแกรมที่รันโปรแกรมอื่น ๆ ทำให้ผู้ใช้สามารถควบคุมโปรแกรมเหล่านี้และตรวจสอบตัวแปรเมื่อเกิดปัญหาขึ้น
GNU Debugger ซึ่งเรียกอีกอย่างว่า gdb, เป็นดีบักเกอร์ที่ได้รับความนิยมสูงสุดสำหรับระบบ UNIX ในการดีบักโปรแกรม C และ C ++
GNU Debugger ช่วยคุณในการรับข้อมูลเกี่ยวกับสิ่งต่อไปนี้:
หากเกิดการถ่ายโอนข้อมูลหลักแล้วคำสั่งหรือนิพจน์ใดที่โปรแกรมขัดข้อง
หากเกิดข้อผิดพลาดขณะเรียกใช้ฟังก์ชันบรรทัดใดของโปรแกรมที่มีการเรียกใช้ฟังก์ชันนั้นและพารามิเตอร์คืออะไร
ค่าของตัวแปรโปรแกรม ณ จุดใดจุดหนึ่งในระหว่างการทำงานของโปรแกรมคืออะไร?
ผลลัพธ์ของนิพจน์เฉพาะในโปรแกรมคืออะไร?
GDB แก้จุดบกพร่องอย่างไร
GDB ช่วยให้คุณสามารถรันโปรแกรมได้จนถึงจุดหนึ่งจากนั้นหยุดและพิมพ์ค่าของตัวแปรบางตัว ณ จุดนั้นหรือทำตามโปรแกรมทีละบรรทัดและพิมพ์ค่าของตัวแปรแต่ละตัวหลังจากดำเนินการแต่ละบรรทัด
GDB ใช้อินเทอร์เฟซบรรทัดคำสั่งง่ายๆ
สิ่งที่ควรทราบ
แม้ว่า GDB จะช่วยคุณในการค้นหาจุดบกพร่องที่เกี่ยวข้องกับการรั่วไหลของหน่วยความจำ แต่ก็ไม่ใช่เครื่องมือในการตรวจจับการรั่วไหลของหน่วยความจำ
ไม่สามารถใช้ GDB สำหรับโปรแกรมที่คอมไพล์มีข้อผิดพลาดและไม่ได้ช่วยในการแก้ไขข้อผิดพลาดเหล่านั้น
ก่อนที่คุณจะทำการติดตั้งตรวจสอบว่าคุณได้ติดตั้ง gdb ในระบบ Unix แล้วหรือไม่โดยออกคำสั่งต่อไปนี้:
$gdb -help
หากติดตั้ง GDB แล้วจะแสดงตัวเลือกทั้งหมดที่มีอยู่ภายใน GDB ของคุณ หากไม่ได้ติดตั้ง GDB ให้ดำเนินการติดตั้งใหม่
คุณสามารถติดตั้ง GDB บนระบบของคุณได้โดยทำตามขั้นตอนง่ายๆที่กล่าวถึงด้านล่าง
step 1: ตรวจสอบให้แน่ใจว่าคุณมีข้อกำหนดเบื้องต้นในการติดตั้ง gdb:
คอมไพเลอร์ C ที่สอดคล้องกับ ANSI (แนะนำให้ใช้ gcc - โปรดทราบว่า gdb สามารถดีบักโค้ดที่สร้างโดยคอมไพเลอร์อื่น ๆ )
จำเป็นต้องมีเนื้อที่ว่างบนดิสก์ 115 MB บนพาร์ติชันที่คุณกำลังจะสร้าง gdb
จำเป็นต้องมีเนื้อที่ว่างบนดิสก์ 20 MB บนพาร์ติชันที่คุณกำลังจะติดตั้ง gdb
โปรแกรมคลายการบีบอัดของ GNU gzip
make ยูทิลิตี้ - รุ่น GNU เป็นที่ทราบกันดีว่าทำงานได้โดยไม่มีปัญหาคนอื่น ๆ ก็อาจทำได้เช่นกัน
step 2: ดาวน์โหลดการแจกจ่ายซอร์ส gdb จาก ftp.gnu.org/gnu/gdb. (เราใช้ gdb-6.6.tar.gz สำหรับคำแนะนำเหล่านี้) วางไฟล์การแจกจ่ายในไดเร็กทอรีบิลด์ของคุณ
step 3:ในไดเร็กทอรีบิลด์ของคุณคลายการบีบอัด gdb-6.6.tar.gz และแตกไฟล์ต้นทางจากไฟล์เก็บถาวร เมื่อแตกไฟล์เสร็จแล้วให้เปลี่ยนไดเร็กทอรีการทำงานของคุณเป็นไดเร็กทอรี gdb-6.6 ที่สร้างขึ้นโดยอัตโนมัติในไดเร็กทอรีบิลด์ของคุณ
$ build> gzip -d gdb-6.6.tar.gz
$ build> tar xfv gdb-6.6.tar
$ build> cd gdb-6.6
step 4: รันสคริปต์กำหนดค่าเพื่อกำหนดค่าโครงสร้างต้นทางสำหรับแพลตฟอร์มของคุณ
$ gdb-6.6> .⁄configure
step 5: สร้าง gdb โดยใช้ไฟล์ make ยูทิลิตี้
$ gdb-6.6> make
step 6: ล็อกอินด้วยรูทและติดตั้ง gdb โดยใช้คำสั่งต่อไปนี้
$ gdb-6.6> make install
step 7: หากต้องการพื้นที่ดิสก์สามารถเรียกคืนได้โดยการลบไดเร็กทอรี gdb build และไฟล์เก็บถาวรหลังจากการติดตั้งเสร็จสมบูรณ์
$ gdb-6.6> cd ..
$ build> rm -r gdb-6.6
$ build> rm gdb-6.6.tar
ตอนนี้คุณได้ติดตั้ง gdb ในระบบของคุณแล้วและพร้อมใช้งาน
ก Debugging Symbol Tableแมปคำแนะนำในโปรแกรมไบนารีที่คอมไพล์กับตัวแปรฟังก์ชันหรือบรรทัดที่เกี่ยวข้องในซอร์สโค้ด การทำแผนที่นี้อาจเป็นดังนี้:
คำสั่งโปรแกรม⇒ชื่อรายการประเภทรายการไฟล์ต้นฉบับหมายเลขบรรทัดที่กำหนด
ตารางสัญลักษณ์อาจถูกฝังลงในโปรแกรมหรือจัดเก็บเป็นไฟล์แยกต่างหาก ดังนั้นหากคุณวางแผนที่จะดีบักโปรแกรมของคุณคุณจะต้องสร้างตารางสัญลักษณ์ซึ่งจะมีข้อมูลที่จำเป็นในการดีบักโปรแกรม
เราสามารถสรุปข้อเท็จจริงเกี่ยวกับตารางสัญลักษณ์ต่อไปนี้:
ตารางสัญลักษณ์ใช้งานได้กับโปรแกรมเวอร์ชันใดเวอร์ชันหนึ่ง - หากโปรแกรมเปลี่ยนแปลงต้องสร้างตารางใหม่
การสร้างดีบักมักมีขนาดใหญ่และช้ากว่าการสร้างแบบขายปลีก (ไม่ใช่การแก้ปัญหา) การสร้างการแก้ปัญหาประกอบด้วยตารางสัญลักษณ์และข้อมูลเสริมอื่น ๆ
หากคุณต้องการดีบักโปรแกรมไบนารีที่คุณไม่ได้คอมไพล์เองคุณต้องได้รับตารางสัญลักษณ์จากผู้เขียน
เพื่อให้ GDB สามารถอ่านข้อมูลทั้งหมดทีละบรรทัดจากตารางสัญลักษณ์เราจำเป็นต้องรวบรวมข้อมูลให้แตกต่างกันเล็กน้อย โดยปกติเรารวบรวมโปรแกรมของเราเป็น:
gcc hello.cc -o hello
แทนที่จะทำสิ่งนี้เราต้องคอมไพล์ด้วยแฟล็ก -g ดังที่แสดงด้านล่าง:
gcc -g hello.cc -o hello
GDB มีรายการคำสั่งจำนวนมากอย่างไรก็ตามคำสั่งต่อไปนี้เป็นคำสั่งที่ใช้บ่อยที่สุด:
b main - กำหนดจุดพักที่จุดเริ่มต้นของโปรแกรม
b - วางเบรกพอยต์ที่บรรทัดปัจจุบัน
b N - กำหนดจุดพักที่บรรทัด N
b +N - วางเบรกพอยต์ N เส้นลงจากบรรทัดปัจจุบัน
b fn - กำหนดจุดพักที่จุดเริ่มต้นของฟังก์ชัน "fn"
d N - ลบหมายเลขเบรกพอยต์ N
info break - รายการเบรกพอยต์
r - รันโปรแกรมจนกว่าจุดพักหรือข้อผิดพลาด
c - รันโปรแกรมต่อไปจนถึงจุดพักหรือข้อผิดพลาดถัดไป
f - รันจนกว่าฟังก์ชันปัจจุบันจะเสร็จสิ้น
s - รันบรรทัดถัดไปของโปรแกรม
s N - รัน N บรรทัดถัดไปของโปรแกรม
n - ชอบ s แต่ไม่เข้าขั้นเป็นฟังก์ชัน
u N - รันจนกว่าคุณจะได้ N บรรทัดหน้าบรรทัดปัจจุบัน
p var - พิมพ์ค่าปัจจุบันของตัวแปร "var"
bt - พิมพ์การติดตามสแต็ก
u - เพิ่มระดับในสแต็ก
d - ลดระดับลงในสแต็ก
q - ออกจาก gdb
เริ่มต้นใช้งาน: การเริ่มต้นและการหยุด
gcc -g myprogram.c
คอมไพล์ myprogram.c ด้วยอ็อพชันการดีบัก (-g) คุณยังคงได้รับ a.out แต่มีข้อมูลการดีบักที่ช่วยให้คุณใช้ตัวแปรและชื่อฟังก์ชันภายใน GDB แทนตำแหน่งหน่วยความจำดิบ (ไม่ใช่เรื่องสนุก)
gdb a.out
เปิด GDB ด้วยไฟล์ a.out แต่ไม่ได้เรียกใช้โปรแกรม คุณจะเห็นข้อความแจ้ง (gdb) - ตัวอย่างทั้งหมดมาจากพรอมต์นี้
r
r arg1 arg2
r <file1
สามวิธีในการเรียกใช้“ a.out” ซึ่งโหลดไว้ก่อนหน้านี้ คุณสามารถเรียกใช้โดยตรง (r) ส่งผ่านอาร์กิวเมนต์ (r arg1 arg2) หรือฟีดในไฟล์ โดยปกติคุณจะกำหนดจุดพักก่อนที่จะทำงาน
help
h เบรกพอยต์
แสดงหัวข้อวิธีใช้ (ความช่วยเหลือ) หรือรับความช่วยเหลือในหัวข้อเฉพาะ (h เบรกพอยต์) GDB ได้รับการบันทึกไว้เป็นอย่างดี
q - ออกจาก GDB
ก้าวผ่านรหัส
Stepping ช่วยให้คุณสามารถติดตามเส้นทางของโปรแกรมของคุณและเป็นศูนย์ในโค้ดที่หยุดทำงานหรือส่งคืนอินพุตที่ไม่ถูกต้อง
l
ล. 50
ล
แสดงรายการซอร์สโค้ด 10 บรรทัดสำหรับบรรทัดปัจจุบัน (l) บรรทัดเฉพาะ (l 50) หรือสำหรับฟังก์ชัน (l myfunction)
ต่อไป
รันโปรแกรมจนถึงบรรทัดถัดไปจากนั้นหยุดชั่วคราว หากบรรทัดปัจจุบันเป็นฟังก์ชันฟังก์ชันนี้จะเรียกใช้ฟังก์ชันทั้งหมดจากนั้นหยุดชั่วคราวnext เหมาะสำหรับการเดินผ่านโค้ดของคุณอย่างรวดเร็ว
ขั้นตอน
รันคำสั่งถัดไปไม่ใช่บรรทัด หากคำสั่งปัจจุบันกำลังตั้งค่าตัวแปรจะเหมือนกับnext. ถ้าเป็นฟังก์ชันมันจะกระโดดเข้าสู่ฟังก์ชันเรียกใช้คำสั่งแรกจากนั้นหยุดชั่วคราวstep เหมาะสำหรับการดำน้ำลึกลงไปในรายละเอียดของรหัสของคุณ
เสร็จสิ้น
เสร็จสิ้นการเรียกใช้ฟังก์ชันปัจจุบันจากนั้นหยุดชั่วคราว (เรียกอีกอย่างว่า step out) มีประโยชน์หากคุณบังเอิญก้าวเข้าสู่ฟังก์ชัน
จุดพักหรือจุดชมวิว
เบรกพอยต์มีบทบาทสำคัญในการดีบัก พวกเขาหยุด (หยุดพัก) โปรแกรมชั่วคราวเมื่อถึงจุดหนึ่ง คุณสามารถตรวจสอบและเปลี่ยนแปลงตัวแปรและดำเนินการต่อได้ สิ่งนี้มีประโยชน์เมื่อเกิดความล้มเหลวในการป้อนข้อมูลหรือต้องทดสอบอินพุต
แตก 45
ทำลายการทำงานของฉัน
- ตั้งเบรกพอยต์ที่บรรทัด 45 หรือที่ฟังก์ชันของฉัน โปรแกรมจะหยุดชั่วคราวเมื่อถึงจุดพัก
ดู x == 3
ตั้งค่า watchpoint ซึ่งจะหยุดโปรแกรมชั่วคราวเมื่อเงื่อนไขเปลี่ยนไป (เมื่อ x == 3 เปลี่ยน) Watchpoints เหมาะสำหรับอินพุตบางอย่าง (myPtr! = NULL) โดยไม่ต้องหยุดการเรียกใช้ฟังก์ชันทุกครั้ง
ดำเนินการต่อ
ดำเนินการต่อหลังจากถูกหยุดชั่วคราวโดยเบรกพอยต์ / จุดเฝ้าระวัง โปรแกรมจะดำเนินต่อไปจนกว่าจะถึงจุดพัก / จุดเฝ้าระวังถัดไป
ลบ N
- ลบเบรกพอยต์ N (เบรกพอยต์จะมีหมายเลขเมื่อสร้าง)
การตั้งค่าตัวแปร
การดูและการเปลี่ยนแปลงตัวแปรที่รันไทม์เป็นส่วนสำคัญของการดีบัก ลองป้อนข้อมูลที่ไม่ถูกต้องให้กับฟังก์ชันหรือเรียกใช้กรณีทดสอบอื่น ๆ เพื่อค้นหาสาเหตุที่แท้จริงของปัญหา โดยปกติคุณจะดู / ตั้งค่าตัวแปรเมื่อโปรแกรมหยุดชั่วคราว
พิมพ์ x
พิมพ์ค่าปัจจุบันของตัวแปร x ความสามารถในการใช้ชื่อตัวแปรดั้งเดิมเป็นสาเหตุที่ต้องใช้แฟล็ก (-g) โปรแกรมที่คอมไพล์เป็นประจำจะลบข้อมูลนี้ออกไป
ตั้งค่า x = 3
ตั้งค่า x = y
- ตั้งค่า x เป็นค่าชุด (3) หรือตัวแปรอื่น (y)
โทร myfunction ()
เรียก myotherfunction (x)
โทร strlen (mystring)
เรียกใช้ฟังก์ชันที่ผู้ใช้กำหนดหรือระบบ สิ่งนี้มีประโยชน์อย่างยิ่ง แต่ระวังการเรียกใช้ฟังก์ชันบั๊กกี้
แสดง x
แสดงค่าของตัวแปร x อย่างต่อเนื่องซึ่งจะแสดงหลังจากทุกขั้นตอนหรือหยุดชั่วคราว มีประโยชน์หากคุณตรวจสอบค่าที่แน่นอนอยู่ตลอดเวลา
ไม่แสดง x
- ลบการแสดงค่าคงที่ของตัวแปรที่แสดงโดยคำสั่ง display
Backtrace และการเปลี่ยนเฟรม
สแต็กคือรายการของการเรียกใช้ฟังก์ชันปัจจุบันซึ่งจะแสดงตำแหน่งที่คุณอยู่ในโปรแกรม กรอบเก็บรายละเอียดของการเรียกใช้ฟังก์ชันเดียวเช่นการขัดแย้ง
bt
Backtracesหรือพิมพ์สแต็กฟังก์ชันปัจจุบันเพื่อแสดงตำแหน่งที่คุณอยู่ในโปรแกรมปัจจุบัน หากสายหลักทำงาน a () ซึ่งเรียก b () ซึ่งเรียก c () backtrace คือ
c <= current location
b
a
main
up
ลง
เลื่อนไปที่เฟรมถัดไปขึ้นหรือลงในกองฟังก์ชัน ถ้าคุณอยู่ในc, คุณสามารถย้ายไปที่ b หรือ a เพื่อตรวจสอบตัวแปรท้องถิ่น
กลับ
- ส่งกลับจากฟังก์ชันปัจจุบัน
การจัดการสัญญาณ
สัญญาณคือข้อความที่เกิดขึ้นหลังจากเหตุการณ์บางอย่างเช่นตัวจับเวลาหรือข้อผิดพลาด GDB อาจหยุดชั่วคราวเมื่อพบสัญญาณ คุณอาจต้องการเพิกเฉยแทน
จัดการ [ชื่อสัญญาณ] [การกระทำ]
ด้ามจับ SIGUSR1 nostop
จัดการกับ SIGUSR1 noprint
จัดการกับ SIGUSR1 ละเว้น
สั่งให้ GDB ละเว้นสัญญาณบางอย่าง (SIGUSR1) เมื่อเกิดขึ้น การละเว้นมีหลายระดับ
ดูตัวอย่างต่อไปนี้เพื่อทำความเข้าใจขั้นตอนการดีบักโปรแกรมและคอร์ที่ดัมพ์
ตัวอย่างการดีบัก 1
ตัวอย่างนี้แสดงให้เห็นว่าคุณจะจับข้อผิดพลาดที่เกิดขึ้นได้อย่างไรเนื่องจากมีข้อยกเว้นที่เพิ่มขึ้นในขณะที่หารด้วยศูนย์
ตัวอย่างการดีบัก 2
ตัวอย่างนี้แสดงให้เห็นถึงโปรแกรมที่สามารถดัมพ์คอร์ได้เนื่องจากหน่วยความจำที่ไม่ได้เริ่มต้น
ทั้งสองโปรแกรมเขียนด้วย C ++ และสร้างคอร์ดัมพ์เนื่องจากเหตุผลที่แตกต่างกัน หลังจากผ่านสองตัวอย่างนี้แล้วคุณควรอยู่ในตำแหน่งที่จะดีบักโปรแกรม C หรือ C ++ ที่สร้างการถ่ายโอนข้อมูลหลัก
หลังจากอ่านบทช่วยสอนนี้แล้วคุณจะต้องมีความเข้าใจเป็นอย่างดีเกี่ยวกับการดีบักโปรแกรม C หรือ C ++ โดยใช้ GNU Debugger ตอนนี้คุณควรเรียนรู้การทำงานของดีบักเกอร์อื่น ๆ ได้ง่ายมากเพราะคล้ายกับ GDB มาก ขอแนะนำอย่างยิ่งให้คุณตรวจสอบผู้ตรวจแก้จุดบกพร่องอื่น ๆ ด้วยเพื่อทำความคุ้นเคยกับคุณสมบัติของพวกเขา
มีตัวแก้จุดบกพร่องที่ดีอยู่ไม่น้อยในตลาด:
DBX Debugger- นี่เรือบั๊กพร้อมกับ Sun Solaris และคุณจะได้รับข้อมูลที่สมบูรณ์เกี่ยวกับบั๊กนี้โดยใช้หน้าคนของ DBX คือDBX คน
DDD Debugger- นี่เป็นเวอร์ชันกราฟิกของ dbx และสามารถใช้งานได้ฟรีบน Linux จะมีรายละเอียดที่สมบูรณ์ใช้หน้าคนของวววคือวววคน
คุณสามารถดูรายละเอียดที่ครอบคลุมเกี่ยวกับ GNU Debugger ได้จากลิงค์ต่อไปนี้: การดีบักด้วย GDB