Watchpoint — ما هو، أنواعه وإعداد نقاط المراقبة في Xcode

المؤلف: IT Sectr نُشر: 2026-05-07 وقت القراءة: 8 دق

Watchpoint (نقطة المراقبة) — آلية تصحيح توقف تنفيذ البرنامج عند تغيير قيمة متغير محدد أو منطقة ذاكرة. على عكس breakpoint المرتبط بسطر كود، فإن watchpoint يتتبع تغييرات البيانات بغض النظر عن مكان حدوث التعديل في البرنامج. وفقًا لـ Apple Developer Documentation، فإن watchpoints لا غنى عنها لتصحيح سباقات البيانات والتغييرات غير المتوقعة للخصائص وتتبع دورة حياة الكائنات.

الرئيسية

  • Watchpoint — نقطة مراقبة لتغير المتغير، تُفعّل عند أي كتابة في منطقة الذاكرة المحددة.
  • Xcode يدعم watchpoints عبر الواجهة الرسومية ووحدة تحكم LLDB، بما في ذلك نقاط المراقبة الشرطية.
  • متغيرات الخصائص للكائنات تتطلب watchpoint مع عنوان الذاكرة بدلاً من اسم المتغير.
  • الأداء مع watchpoints ينخفض بشكل كبير بسبب المراقبة العتادية لكل عملية كتابة.
  • Watchpoints لا تُحفظ بين جلسات التصحيح — يجب إعدادها مرة أخرى بعد كل تشغيل.

ما هو watchpoint ومبدأ العمل

Watchpoint — هي آلية مصحح توقف تنفيذ البرنامج عندما تتغير القيمة في عنوان ذاكرة محدد. إذا كان breakpoint يتفاعل عند الوصول إلى سطر كود معين، فإن watchpoint يتفاعل عند الكتابة في خلية ذاكرة محددة — بغض النظر عن أي جزء من الكود قام بالكتابة. هذا يجعله لا غنى عنه للعثور على تعديلات غير متوقعة للمتغيرات، خاصة في التطبيقات متعددة الخيوط.

يعتمد مبدأ العمل على الدعم العتادي للمعالج. توفر شرائح ARM الحديثة (Apple Silicon، Qualcomm Snapdragon) من 4 إلى 8 سجلات watchpoint عتادية. عندما ينفذ المعالج تعليمة كتابة إلى عنوان يطابق 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 السابقة

الإعداد عبر واجهة Xcode الرسومية

في Xcode، يمكنك إعداد watchpoint عبر منطقة التصحيح: توقف عند breakpoint، ابحث عن المتغير المطلوب في لوحة Variables View، انقر بزر الماوس الأيمن واختر Watch Variable. سيقوم Xcode تلقائيًا بتنفيذ الأمر watchpoint set variable مع اسم المتغير الصحيح والسياق. بعد ذلك، سيتوقف المصحح عند كل تغيير قيمة — مناسب للتصحيح السريع دون التبديل إلى وحدة التحكم. ومع ذلك، تعمل هذه الطريقة فقط طالما كان المتغير في نطاق الإطار الحالي.

swift
func processItems(_ items: [String]) {
    var index = 0
    // قم بتعيين watchpoint على الفهرس عبر الواجهة الرسومية:
    // توقف هنا، انقر بزر الماوس الأيمن → Watch Variable
    for item in items {
        index += 1
        print("العنصر \(index): \(item)")
    }
}

إدارة watchpoints عبر LLDB

LLDB يوفر مجموعة كاملة من الأوامر لإدارة watchpoints من وحدة التحكم. هذا يعطي تحكمًا أكبر من الواجهة الرسومية: يمكنك تعيين حجم منطقة المراقبة، تحديد شروط التفعيل، إنشاء 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 عند إعادة تخصيص الذاكرة. عند تفعيل جمع القمامة أو 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               # حذف جميع نقاط المراقبة
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. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا