ฉันใช้งานแอพพลิเคชั่นผ่าน gdb และฉันต้องการตั้งค่าเบรกพอยต์เมื่อใดก็ตามที่มีการเข้าถึง / เปลี่ยนแปลงตัวแปรเฉพาะ มีวิธีที่ดีในการทำเช่นนี้หรือไม่? ฉันยังสนใจวิธีอื่น ๆ ในการตรวจสอบตัวแปรใน C / C ++ เพื่อดูว่า / เมื่อมันเปลี่ยนแปลง
ฉันใช้งานแอพพลิเคชั่นผ่าน gdb และฉันต้องการตั้งค่าเบรกพอยต์เมื่อใดก็ตามที่มีการเข้าถึง / เปลี่ยนแปลงตัวแปรเฉพาะ มีวิธีที่ดีในการทำเช่นนี้หรือไม่? ฉันยังสนใจวิธีอื่น ๆ ในการตรวจสอบตัวแปรใน C / C ++ เพื่อดูว่า / เมื่อมันเปลี่ยนแปลง
คำตอบ:
ดูเฉพาะการหยุดพักการเขียนrwatchให้คุณหยุดอ่านและawatchให้คุณหยุดอ่าน / เขียน
คุณสามารถตั้งค่า watchpoints ที่อ่านในตำแหน่งหน่วยความจำ:
gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface
แต่มีข้อ จำกัด หนึ่งข้อที่ใช้กับคำสั่ง rwatch และ awatch; คุณไม่สามารถใช้ตัวแปร gdb ในนิพจน์:
gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.
ดังนั้นคุณต้องขยายพวกเขาเอง:
gdb$ print $ebx
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()
แก้ไข:โอ้และโดยวิธีการ คุณจำเป็นต้องมีทั้งฮาร์ดแวร์หรือซอฟต์แวร์ที่สนับสนุน ซอฟต์แวร์ช้าลงอย่างเห็นได้ชัดมาก ในการตรวจสอบว่าระบบปฏิบัติการของคุณรองรับจุดเฝ้าดูฮาร์ดแวร์หรือไม่คุณสามารถดูการตั้งค่าสภาพแวดล้อมcan-use-hw-watchpoints
gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
print &variable
watch
คำสั่ง ในขณะเดียวกันนี้เป็นคำถามที่กำปั้นที่ปรากฏในใจหลังจากอ่านข้างต้น กี่ไบต์rwatch *0xfeedface
จะดูจริง ๆ ?
rwatch *(int *)0xfeedface
และมันจะดูsizeof(int)
ไบต์: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints html
สิ่งที่คุณกำลังมองหาเรียกว่าจุดเฝ้าดู
การใช้
(gdb) watch foo
: ดูค่าของตัวแปร foo
(gdb) watch *(int*)0x12345678
: ดูค่าที่ชี้ไปตามที่อยู่และเลือกประเภทที่คุณต้องการ
(gdb) watch a*b + c/d
: ดูการแสดงออกที่ซับซ้อนโดยพลการที่ถูกต้องในภาษาพื้นเมืองของโปรแกรม
จุดชมวิวมีสามประเภท:
คุณสามารถเลือกสิ่งที่เหมาะสมกว่าสำหรับความต้องการของคุณ
สำหรับข้อมูลเพิ่มเติมโปรดตรวจสอบนี้ออก
การสมมติว่าคำตอบแรกนั้นหมายถึงไวยากรณ์ C-like (char *)(0x135700 +0xec1a04f)
ดังนั้นคำตอบที่ต้องทำrwatch *0x135700+0xec1a04f
นั้นไม่ถูกต้อง rwatch *(0x135700+0xec1a04f)
ไวยากรณ์ที่ถูกต้องคือ
การขาดสิ่งเหล่า()
นี้ทำให้ฉันเจ็บปวดอย่างมากในการพยายามใช้จุดเฝ้าระวังตัวเอง
ฉันลองต่อไปนี้:
$ cat gdbtest.c
int abc = 43;
int main()
{
abc = 10;
}
$ gcc -g -o gdbtest gdbtest.c
$ gdb gdbtest
...
(gdb) watch abc
Hardware watchpoint 1: abc
(gdb) r
Starting program: /home/mweerden/gdbtest
...
Old value = 43
New value = 10
main () at gdbtest.c:6
6 }
(gdb) quit
ดูเหมือนเป็นไปได้ แต่คุณต้องการการสนับสนุนฮาร์ดแวร์
ใช้การเฝ้าดูเพื่อดูว่าตัวแปรถูกเขียนไปเมื่อใดและอ่านแล้วและจับตาดูเมื่อมีการอ่าน / เขียนจาก / ถึงตามที่ระบุไว้ข้างต้น อย่างไรก็ตามโปรดทราบว่าในการใช้คำสั่งนี้คุณจะต้องหยุดโปรแกรมและตัวแปรจะต้องอยู่ในขอบเขตเมื่อคุณเสียโปรแกรม:
ใช้คำสั่ง watch อาร์กิวเมนต์ของคำสั่ง watch คือนิพจน์ที่ถูกประเมิน นี่หมายความว่าตัวแปรที่คุณต้องการตั้งค่า watchpoint จะต้องอยู่ในขอบเขตปัจจุบัน ดังนั้นในการตั้งค่า watchpoint บนตัวแปรที่ไม่ใช่โกลบอลคุณต้องตั้งค่าเบรกพอยต์ที่จะหยุดโปรแกรมของคุณเมื่อตัวแปรนั้นอยู่ในขอบเขต คุณตั้งค่า watchpoint หลังจากโปรแกรมแบ่ง
watch -location mTextFormatted
ผมพบว่าตัวแปรนี้มีประโยชน์อย่างมาก: