Watchpoint — จุดสังเกตคืออะไร ประเภทและการตั้งค่าใน Xcode

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-07 เวลาอ่าน: 8 นาที

Watchpoint (จุดสังเกต) — กลไกการดีบักที่หยุดการทำงานของโปรแกรมเมื่อค่าเปลี่ยนแปลงของตัวแปรหรือพื้นที่หน่วยความจำที่ระบุ แตกต่างจาก breakpoint ที่ผูกติดกับบรรทัดของโค้ด watchpoint จะติดตามการเปลี่ยนแปลงข้อมูลไม่ว่าส่วนใดของโปรแกรมที่มีการแก้ไขก็ตาม ตาม Apple Developer Documentation แล้ว watchpoints เป็นสิ่งที่ขาดไม่ได้สำหรับการดีบักเรซข้อมูล การเปลี่ยนแปลงคุณสมบัติที่ไม่คาดคิด และการติดตามวงจรชีวิตของออบเจ็กต์

ประเด็นสำคัญ

  • Watchpoint — จุดที่เฝ้าดูการเปลี่ยนแปลงของตัวแปร ทำงานเมื่อมีการเขียนไปยังพื้นที่หน่วยความจำที่ระบุ
  • Xcode รองรับ watchpoints ผ่าน GUI และคอนโซล LLDB รวมถึง watchpoints แบบมีเงื่อนไข
  • ตัวแปรคุณสมบัติ ของออบเจ็กต์ต้องการ watchpoint ที่มีที่อยู่หน่วยความจำแทนชื่อตัวแปร
  • ประสิทธิภาพ กับ watchpoints ลดลงอย่างมากเนื่องจากมีการตรวจสอบฮาร์ดแวร์ทุกการดำเนินการเขียน
  • Watchpoints จะไม่ถูกเก็บรักษาระหว่างเซสชันการดีบัก — ต้องตั้งค่าใหม่ทุกครั้งหลังจากเริ่มการทำงาน

Watchpoint คืออะไรและหลักการทำงาน

Watchpoint — เป็นกลไกของดีบักเกอร์ที่หยุดการทำงานของโปรแกรมเมื่อค่าที่อยู่หน่วยความจำที่ระบุเปลี่ยนแปลง หาก breakpoint ตอบสนองเมื่อถึงบรรทัดโค้ดที่กำหนด watchpoint จะตอบสนองเมื่อมีการเขียนไปยังเซลล์หน่วยความจำที่ระบุ — ไม่ว่าส่วนใดของโค้ดจะเป็นผู้เขียน ทำให้มันเป็นสิ่งที่ขาดไม่ได้ในการค้นหาการแก้ไขตัวแปรที่ไม่คาดคิด โดยเฉพาะในแอปพลิเคชันแบบหลายเธรด

หลักการทำงานขึ้นอยู่กับการสนับสนุนฮาร์ดแวร์ของโปรเซสเซอร์ ชิป ARM สมัยใหม่ (Apple Silicon, Qualcomm Snapdragon) มีรีจิสเตอร์ watchpoint แบบฮาร์ดแวร์ 4 ถึง 8 ตัว เมื่อโปรเซสเซอร์ดำเนินการคำสั่งเขียนไปยังที่อยู่ที่ตรงกับ watchpoint จะเกิด การขัดจังหวะฮาร์ดแวร์ ซึ่งดีบักเกอร์จะจับไว้ เมื่อรีจิสเตอร์ฮาร์ดแวร์หมด LLDB จะเปลี่ยนเป็นโหมดซอฟต์แวร์ — มันจะตรวจสอบทุกคำสั่งเขียนทีละขั้น ทำให้การทำงานช้าลงหลายสิบเท่า

ตาม ARM Architecture Reference Manual แล้ว watchpoints แบบฮาร์ดแวร์ทำงานที่ระดับโมดูล Data Watchpoint and Trace (DWT) และไม่ต้องการการแก้ไขโค้ดที่ปฏิบัติการได้ เวลาตอบสนองเป็นนาโนวินาที ทำให้สามารถติดตามการเปลี่ยนแปลงตัวแปรความถี่สูงในลูปการประมวลผลข้อมูล เช่น บัฟเฟอร์เสียงหรือเฟรมวิดีโอ

เมื่อใดที่ watchpoint มีประสิทธิภาพมากกว่า breakpoint

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

ประเภทของ watchpoints และวิธีการตั้งค่า

Xcode และ LLDB รองรับ watchpoints สามประเภท: watchpoint set variable — สำหรับเฝ้าดูตัวแปรภายใน; watchpoint set expression — สำหรับเฝ้าดูนิพจน์ที่ส่งคืนที่อยู่; watchpoint set — สำหรับเฝ้าดูที่อยู่หน่วยความจำดิบ แต่ละประเภทมีขอบเขตการใช้งานของตัวเอง

ประเภท watchpointคำสั่ง LLDBการใช้งาน
ตัวแปรwatchpoint set variable -w write self.countตัวแปรภายในและทั่วโลก คุณสมบัติของโครงสร้าง
นิพจน์watchpoint set expression -w write -- &self->mutex.lockฟิลด์ของโครงสร้างผ่านพอยน์เตอร์ สมาชิกของอาร์เรย์ผ่านดัชนี
ที่อยู่watchpoint set -w write 0x600000c4b80ที่อยู่หน่วยความจำเฉพาะจากผลลัพธ์ LLDB ก่อนหน้า

การตั้งค่าผ่าน GUI ของ Xcode

ใน Xcode คุณสามารถตั้งค่า watchpoint ผ่านพื้นที่ดีบัก: หยุดที่ breakpoint ค้นหาตัวแปรที่ต้องการในแผง Variables View คลิกขวาและเลือก Watch Variable Xcode จะดำเนินการคำสั่ง watchpoint set variable โดยอัตโนมัติด้วยชื่อตัวแปรและบริบทที่ถูกต้อง หลังจากนั้น ดีบักเกอร์จะหยุดทุกครั้งที่มีการเปลี่ยนแปลงค่า — สะดวกสำหรับการดีบักอย่างรวดเร็วโดยไม่ต้องสลับไปที่คอนโซล อย่างไรก็ตาม วิธีนี้ใช้ได้เฉพาะเมื่อตัวแปรอยู่ในขอบเขตของเฟรมปัจจุบัน

swift
func processItems(_ items: [String]) {
    var index = 0
    // ตั้ง watchpoint บน index ผ่าน GUI:
    // หยุดที่นี่ คลิกขวา → Watch Variable
    for item in items {
        index += 1
        print("รายการ \(index): \(item)")
    }
}

จัดการ watchpoints ผ่าน LLDB

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

คำสั่ง watchpoint พื้นฐาน

คำสั่ง watchpoint set variable รับชื่อตัวแปรโดยพิจารณาจากขอบเขต: สำหรับคุณสมบัติ self ของ Objective-C ใช้ self->_property สำหรับ Swift ใช้ self.property พารามิเตอร์ -w write กำหนดการติดตามการเขียน -w read — การติดตามการอ่าน (โหมดที่ใช้ได้เฉพาะในบางสถาปัตยกรรม) -s size — ขนาดพื้นที่เป็นไบต์ หลังจากตั้ง watchpoint คุณสามารถดูรายการด้วยคำสั่ง watchpoint list

lldb
(lldb) watchpoint set variable -w write -s 8 self.balance
Watchpoint 1: addr = 0x600000c4b80 size = 8 state = enabled  type = w
    watchpoint spec: 'self.balance'
(lldb) watchpoint set expression -w write -- self->items._storage
Watchpoint 2: addr = 0x600003a4c00 size = 8
(lldb) watchpoint list
1: location = 0x600000c4b80, type = write, variable = '_balance'
2: location = 0x600003a4c00, type = write, expression = 'self->items._storage'

Watchpoints แบบมีเงื่อนไข

เช่นเดียวกับ breakpoints watchpoints รองรับ การทำงานแบบมีเงื่อนไข พารามิเตอร์ -c กำหนดเงื่อนไขใน Swift หรือ Objective-C ตัวอย่างเช่น watchpoint ที่มีเงื่อนไข newValue > 1000 จะหยุดเฉพาะเมื่อค่าที่เขียนเกินหนึ่งพัน นี่เป็นสิ่งสำคัญเมื่อดีบักลูปหรือเซนเซอร์ที่สร้างการเปลี่ยนแปลงหลายพันครั้งต่อวินาที — มิฉะนั้นดีบักเกอร์จะหยุดทุกการเปลี่ยนแปลง ทำให้ทำงานไม่ได้

lldb
(lldb) watchpoint set variable -w write self.temperature -c "(int)$newValue > 100"
Watchpoint 3: addr = 0x600000e4a20, condition = '(int)$newValue > 100'
(lldb) watchpoint modify 3 -C "po self.temperature" -G true
// บันทึกค่าโดยอัตโนมัติและดำเนินการต่อ

Watchpoints สำหรับคุณสมบัติของออบเจ็กต์และคอลเล็กชัน

คุณลักษณะเฉพาะของ watchpoints สำหรับคุณสมบัติของออบเจ็กต์ Objective-C และ Swift — watchpoint ถูกตั้งค่าไม่ใช่บนชื่อคุณสมบัติแต่บนที่อยู่ของฟิลด์ ivar (ตัวแปรอินสแตนซ์) ในหน่วยความจำของออบเจ็กต์ ซึ่งหมายความว่าทุกครั้งที่มีการจัดสรรออบเจ็กต์ใหม่ (เช่น เมื่อสร้าง ViewController ใหม่) watchpoint จะไม่ถูกต้องเนื่องจากที่อยู่หน่วยความจำเปลี่ยนไป สำหรับการเฝ้าดูคุณสมบัติอย่างต่อเนื่องระหว่างการเริ่มต้นใหม่ คุณต้องตั้ง watchpoint ใหม่ในขณะที่เริ่มต้นออบเจ็กต์

Watchpoint บนสมาชิกของคอลเล็กชัน

การเฝ้าดูสมาชิกของ อาร์เรย์ และ พจนานุกรม ต้องการการคำนวณที่อยู่ของสมาชิกที่ระบุ ตัวอย่างเช่น เพื่อเฝ้าดูสมาชิกตัวที่สามของอาร์เรย์ ใช้ watchpoint set expression -- &array[2] หากอาร์เรย์จัดสรรบัฟเฟอร์ภายในใหม่ (เมื่อเพิ่มสมาชิกเกินความจุ) watchpoint จะไม่ถูกต้อง — LLDB จะรายงานข้อผิดพลาด Watchpoint 1 has an invalid address ในกรณีเช่นนี้ คุณต้องตั้ง watchpoint ใหม่หลังจากเปลี่ยนขนาดของคอลเล็กชัน

lldb
(lldb) expr var $arr = [10, 20, 30, 40, 50]
(lldb) watchpoint set expression -w write -- &$arr[2]
Watchpoint 4: addr = 0x1000a4b20, size = 8
(lldb) expr $arr[2] = 99
Watchpoint 4 hit: old value: 30, new value: 99

การติดตาม retain count ผ่าน watchpoint

ใน Objective-C คุณสามารถติดตาม retain count ของออบเจ็กต์โดยการตั้ง watchpoint บนฟิลด์ retainCount ในโครงสร้าง objc_object LLDB ทำสิ่งนี้ผ่าน watchpoint set expression -w write -- (int*)[object retainCount] อย่างไรก็ตาม สำหรับออบเจ็กต์ Swift ที่มี ARC (การนับการอ้างอิงอัตโนมัติ) retain count ไม่สามารถเข้าถึงได้โดยตรง — ให้ใช้ Instruments หรือ Memory Graph Debugger สำหรับการวิเคราะห์การรั่วไหลแทน ตาม Apple แล้ว watchpoints บน retain count ทำงานเฉพาะในบิลด์ Debug ที่ปิดการปรับแต่ง ARC

ข้อจำกัดและประสิทธิภาพของ watchpoints

Watchpoints มีข้อจำกัดสำคัญหลายประการที่ต้องพิจารณา หลัก — จำนวน watchpoints แบบฮาร์ดแวร์ถูกจำกัดไว้ที่ 4–8 รีจิสเตอร์บนสถาปัตยกรรม ARM และสูงสุด 4 บน x86 เมื่อรีจิสเตอร์ฮาร์ดแวร์ทั้งหมดถูกใช้ LLDB จะเปลี่ยนเป็นโหมด watchpoint แบบซอฟต์แวร์: มันจะปรับเปลี่ยนทุกคำสั่งเขียนในช่วงที่ติดตามเพื่อสร้างข้อยกเว้น ซึ่งทำให้การทำงานช้าลง 10–50 เท่า ดังนั้นในทางปฏิบัติแนะนำให้ใช้ไม่เกิน 2–3 watchpoints ที่ทำงานพร้อมกัน

ข้อจำกัดที่สอง — การไม่ถูกต้องของ watchpoints เมื่อมีการจัดสรรหน่วยความจำใหม่ เมื่อ garbage collection หรือ ARC ทำงาน และออบเจ็กต์ย้ายในหน่วยความจำ (ในภาษาที่มีการบีบอัดฮีป) ที่อยู่ watchpoint จะไม่ถูกต้อง ใน Swift และ Objective-C ARC ไม่ย้ายออบเจ็กต์ แต่การจัดสรรอาร์เรย์และสตริงใหม่ทำให้เกิดผลเดียวกัน LLDB เตือนเกี่ยวกับสิ่งนี้ด้วยข้อความ Watchpoint N address (0x...) doesn’t contain a valid allocation

ข้อจำกัดที่สาม — การมองเห็นของตัวแปร Watchpoint บนตัวแปรภายในทำงานเฉพาะเมื่อตัวแปรนั้นอยู่ในขอบเขตของเฟรมสแต็กปัจจุบัน เมื่อฟังก์ชันสิ้นสุด watchpoint จะถูกลบโดยอัตโนมัติ สำหรับการเฝ้าดูตัวแปรทั่วโลกหรือฟิลด์ของออบเจ็กต์ที่มีอายุยืน watchpoint จะคงอยู่จนกว่าจะถูกลบอย่างชัดเจนผ่าน watchpoint delete หรือจนกว่าโพรเซสจะสิ้นสุด

lldb
(lldb) watchpoint delete 1
1 watchpoints deleted.
(lldb) watchpoint delete               # ลบ watchpoints ทั้งหมด
2 watchpoints deleted.
(lldb) watchpoint disable 1             # ปิดใช้งานชั่วคราว
(lldb) watchpoint enable 1              # เปิดใช้งานอีกครั้ง

ตาม ARM แล้ว watchpoints บน Apple Silicon (M1–M4) รองรับขนาดพื้นที่ที่เฝ้าดูตั้งแต่ 1 ถึง 8 ไบต์ สำหรับการเฝ้าดูโครงสร้างที่ใหญ่กว่า 8 ไบต์ คุณต้องตั้ง watchpoints หลายตัวในแต่ละฟิลด์ นี่เป็นสิ่งสำคัญเมื่อดีบักโครงสร้างข้อมูลที่ซับซ้อน เช่น CGRect (16 ไบต์) หรือ UIEdgeInsets (16 ไบต์)

คำถามที่พบบ่อย

ความแตกต่างระหว่าง watchpoint และ breakpoint คืออะไร?

Breakpoint ผูกติดกับบรรทัดของโค้ด — หยุดเมื่อถึงบรรทัดนั้น Watchpoint ผูกติดกับที่อยู่หน่วยความจำ — หยุดเมื่อมีการเขียนไปยังที่อยู่นั้นจากที่ใดก็ได้ในโปรแกรม Watchpoint ค้นหา “ใครกำลังเปลี่ยนค่า” breakpoint ค้นหา “เกิดอะไรขึ้นในบรรทัดนี้”

สามารถตั้ง watchpoints พร้อมกันได้กี่ตัว?

4–8 watchpoints แบบฮาร์ดแวร์บน ARM (รวม Apple Silicon) การเกินจะทำให้ watchpoint เปลี่ยนเป็นโหมดซอฟต์แวร์ ทำให้การทำงานช้าลง 10–50 เท่า แนะนำให้ใช้ไม่เกิน 2–3 watchpoints ที่ทำงานพร้อมกัน

ทำไม watchpoint หยุดทำงานหลังจากรีสตาร์ทแอปพลิเคชัน?

Watchpoints จะไม่ถูกเก็บรักษาระหว่างเซสชันการดีบัก ทุกครั้งที่เริ่มทำงานใหม่ ที่อยู่หน่วยความจำจะเปลี่ยนแปลงและต้องตั้ง watchpoint ใหม่ ข้อยกเว้นคือ watchpoints บนตัวแปรทั่วโลกที่มีที่อยู่คงที่

ฉันสามารถตั้ง watchpoint บนคุณสมบัติ Swift ได้หรือไม่?

ได้ แต่ watchpoint จะถูกตั้งบน ivar (พื้นที่จัดเก็บสำรอง) ของคุณสมบัติ ไม่ใช่บนคุณสมบัติเอง ใน Swift ให้ใช้ watchpoint set variable self.property — LLDB จะค้นหา ivar ที่สอดคล้องกันโดยอัตโนมัติจากชื่อคุณสมบัติ

Watchpoint ส่งผลต่อประสิทธิภาพของแอปพลิเคชันอย่างไร?

Watchpoints แบบฮาร์ดแวร์ ไม่ส่งผลต่อประสิทธิภาพ — การขัดจังหวะเกิดขึ้นที่ระดับโปรเซสเซอร์ Watchpoints แบบซอฟต์แวร์ (เมื่อรีจิสเตอร์ฮาร์ดแวร์หมด) ทำให้การทำงานช้าลง 10–50 เท่า เนื่องจาก LLDB ตรวจสอบทุกคำสั่งเขียน

สรุป

  • Watchpoint — จุดที่เฝ้าดูการเปลี่ยนแปลงของหน่วยความจำ ทำงานเมื่อมีการเขียนไปยังที่อยู่ที่ระบุจากเธรดใดก็ได้
  • Watchpoints แบบฮาร์ดแวร์ ใช้รีจิสเตอร์ DWT ของโปรเซสเซอร์และไม่ทำให้การทำงานช้าลง แต่จำกัดที่ 4–8 รีจิสเตอร์
  • LLDB รองรับ watchpoints สามประเภท: บนตัวแปร บนนิพจน์ และบนที่อยู่หน่วยความจำดิบ
  • Watchpoints แบบมีเงื่อนไข จะทำงานเฉพาะเมื่อนิพจน์ที่ระบุมีค่าเป็นจริง — จำเป็นสำหรับการดีบักการเปลี่ยนแปลงความถี่สูง
  • Watchpoints บนคุณสมบัติของออบเจ็กต์และสมาชิกของคอลเล็กชันจะไม่ถูกต้องเมื่อมีการจัดสรรหน่วยความจำใหม่
  • Watchpoints จะไม่ถูกเก็บรักษาระหว่างเซสชันและจะถูกลบเมื่อตัวแปรออกจากขอบเขต
  • Watchpoint เป็นตัวเลือกที่ดีที่สุดเมื่อรู้จักตัวแปรแต่ไม่ทราบตำแหน่งที่ถูกแก้ไข โดยเฉพาะในโค้ดแบบหลายเธรด

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม