Watchpoint — چیست، انواع و تنظیم نقاط مشاهده در Xcode

نویسنده: IT Sectr منتشر شده: 2026-05-07 زمان مطالعه: 8 دقیقه

Watchpoint (نقطه مشاهده) — مکانیزم دیباگینگ است که اجرای برنامه را هنگام تغییر مقدار یک متغیر مشخص یا ناحیه حافظه متوقف می‌کند. برخلاف breakpoint که به یک خط کد متصل است، watchpoint تغییر داده را بدون توجه به اینکه در کدام بخش برنامه رخ داده است، ردیابی می‌کند. طبق Apple Developer Documentation، watchpointها برای دیباگ کردن race conditionها، تغییرات غیرمنتظره ویژگی‌ها و ردیابی چرخه حیات اشیاء ضروری هستند.

نکات کلیدی

  • Watchpoint — نقطه مشاهده تغییر متغیر که با هر بار نوشتن در ناحیه حافظه مشخص شده فعال می‌شود.
  • Xcode از watchpointها از طریق GUI و کنسول LLDB، از جمله نقاط مشاهده شرطی پشتیبانی می‌کند.
  • متغیرهای ویژگی اشیاء نیاز به watchpoint با آدرس حافظه دارند، نه نام متغیر.
  • عملکرد با watchpointها به دلیل نظارت سخت‌افزاری هر عملیات نوشتن به طور قابل توجهی کاهش می‌یابد.
  • Watchpointها بین جلسات دیباگ ذخیره نمی‌شوند — باید پس از هر اجرا دوباره تنظیم شوند.

Watchpoint چیست و اصل کار

Watchpoint — مکانیزم دیباگر است که وقتی مقدار در آدرس حافظه مشخص شده تغییر کند، اجرای برنامه را متوقف می‌کند. اگر breakpoint به رسیدن به یک خط کد خاص واکنش نشان می‌دهد، watchpoint به نوشتن در یک خانه حافظه مشخص واکنش نشان می‌دهد — صرف نظر از اینکه کدام بخش کد آن نوشتن را انجام داده است. این ویژگی آن را در جستجوی تغییرات غیرمنتظره متغیرها، به‌ویژه در برنامه‌های چندنخی، ضروری می‌کند.

اصل کار بر پایه پشتیبانی سخت‌افزاری پردازنده است. تراشه‌های مدرن ARM (Apple Silicon, Qualcomm Snapdragon) بین ۴ تا ۸ ثبات سخت‌افزاری watchpoint ارائه می‌دهند. وقتی پردازنده یک دستور نوشتن در آدرسی مطابق با watchpoint اجرا می‌کند، یک وقفه سخت‌افزاری ایجاد می‌شود که دیباگر آن را می‌گیرد. اگر ثبات‌های سخت‌افزاری تمام شوند، LLDB به حالت نرم‌افزاری تغییر می‌کند — هر دستور نوشتن را گام به گام بررسی می‌کند که اجرا را ده‌ها بار کند می‌کند.

طبق ARM Architecture Reference Manual، watchpointهای سخت‌افزاری در سطح ماژول Data Watchpoint and Trace (DWT) کار می‌کنند و نیاز به تغییر کد اجرایی ندارند. زمان واکنش به فعال‌سازی در حد نانوثانیه است که امکان ردیابی تغییرات با فرکانس بالا در حلقه‌های پردازش داده مانند بافرهای صوتی یا فریم‌های ویدیویی را فراهم می‌کند.

چه زمانی watchpoint از breakpoint مؤثرتر است

Watchpoint زمانی ضروری است که می‌دانید کدام متغیر تغییر می‌کند، اما نمی‌دانید از کجا. سناریوهای معمول: مقدار ویژگی frame در UIView بدون دلیل مشخص تغییر می‌کند؛ شمارنده در نخ پس‌زمینه به طور غیرقابل پیش‌بینی بازنشانی می‌شود؛ پرچم isLoading زودتر از اتمام درخواست شبکه تغییر می‌کند. در هر یک از این موارد، تنظیم breakpoint در تمام مکان‌هایی که ممکن است نوشتن رخ دهد، غیرعملی است. Watchpoint مشکل را با یک دستور حل می‌کند.

انواع watchpoint و روش‌های تنظیم

Xcode و LLDB از سه نوع watchpoint پشتیبانی می‌کنند: 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 را از طریق Debug Area تنظیم کرد: روی 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("Item \(index): \(item)")
    }
}

مدیریت watchpointها از طریق LLDB

LLDB مجموعه کاملی از دستورات برای مدیریت watchpointها از کنسول ارائه می‌دهد. این کنترل بیشتری نسبت به GUI فراهم می‌کند: می‌توان اندازه ناحیه مشاهده را تعیین کرد، شرط فعال‌سازی تنظیم کرد، watchpoint روی آدرس‌های به‌دست آمده از عبارات محاسبه شده ایجاد کرد و به طور خودکار هنگام فعال‌سازی اقدامات انجام داد. رابط خط فرمان به‌ویژه در دیباگ سناریوهای پیچیده که نیاز به تغییر سریع پارامترهای مشاهده دارند مفید است.

دستورات اصلی 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'

Watchpointهای شرطی

مانند breakpointها، watchpointها نیز از فعال‌سازی شرطی پشتیبانی می‌کنند. پارامتر -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
// به طور خودکار مقدار را ثبت کرده و اجرا را ادامه دهید

Watchpoint برای ویژگی‌های اشیاء و مجموعه‌ها

ویژگی watchpointها برای ویژگی‌های اشیاء 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 (Automatic Reference Counting) retain count مستقیماً در دسترس نیست — به جای آن از Instruments یا Memory Graph Debugger برای تحلیل نشت حافظه استفاده کنید. طبق Apple، watchpointهای retain count فقط در بیلدهای Debug با ARC غیرفعال کار می‌کنند.

محدودیت‌ها و عملکرد watchpointها

Watchpointها محدودیت‌هایی دارند که باید در نظر گرفته شوند. اصلی‌ترین — تعداد watchpointهای سخت‌افزاری به ۴–۸ ثبات در معماری ARM و تا ۴ در x86 محدود است. وقتی تمام ثبات‌های سخت‌افزاری اشغال شوند، LLDB به حالت watchpoint نرم‌افزاری تغییر می‌کند: هر دستور نوشتن در محدوده ردیابی شده را برای تولید استثنا تغییر می‌دهد. این کار اجرا را ۱۰–۵۰ بار کند می‌کند، بنابراین در عمل توصیه می‌شود هم‌زمان بیش از ۲–۳ watchpoint فعال استفاده نشود.

محدودیت دوم — نامعتبر شدن watchpointها هنگام تخصیص مجدد حافظه. هنگام اجرای garbage collector یا ARC، وقتی شیء در حافظه جابجا می‌شود (در زبان‌های با فشرده‌سازی heap)، آدرس 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               # حذف همه watchpointها
2 watchpoints deleted.
(lldb) watchpoint disable 1             # غیرفعال کردن موقت
(lldb) watchpoint enable 1              # فعال کردن دوباره

طبق ARM، watchpointها در Apple Silicon (M1–M4) اندازه ناحیه ردیابی شده از ۱ تا ۸ بایت را پشتیبانی می‌کنند. برای مشاهده ساختارهای بزرگتر از ۸ بایت باید چندین watchpoint روی هر فیلد تنظیم کرد. این در دیباگ ساختارهای داده پیچیده مانند CGRect (۱۶ بایت) یا UIEdgeInsets (۱۶ بایت) مهم است.

سوالات متداول

تفاوت بین watchpoint و breakpoint چیست؟

Breakpoint به یک خط کد متصل است — با رسیدن به آن متوقف می‌شود. Watchpoint به یک آدرس حافظه متصل است — با نوشتن در آن آدرس از هر جای برنامه متوقف می‌شود. Watchpoint به دنبال «چه کسی مقدار را تغییر می‌دهد» می‌گردد، breakpoint به دنبال «در این خط چه اتفاقی می‌افتد».

چند watchpoint می‌توان همزمان تنظیم کرد؟

۴–۸ سخت‌افزاری روی ARM (شامل Apple Silicon). تجاوز از این حد watchpoint را به حالت نرم‌افزاری منتقل می‌کند که اجرا را ۱۰–۵۰ بار کند می‌کند. توصیه می‌شود همزمان بیش از ۲–۳ watchpoint فعال نداشته باشید.

چرا watchpoint پس از راه‌اندازی مجدد برنامه کار نمی‌کند؟

Watchpointها بین جلسات دیباگ ذخیره نمی‌شوند. با هر اجرای جدید آدرس‌های حافظه تغییر می‌کنند و watchpoint باید دوباره تنظیم شود. استثنا — watchpoint روی متغیرهای سراسری با آدرس ثابت.

آیا می‌توان روی ویژگی Swift watchpoint تنظیم کرد؟

بله، اما watchpoint روی ivar (ذخیره پشتیبان) ویژگی تنظیم می‌شود، نه روی خود ویژگی. در Swift از watchpoint set variable self.property استفاده کنید — LLDB به طور خودکار ivar مربوطه را بر اساس نام ویژگی پیدا می‌کند.

watchpoint چگونه بر عملکرد برنامه تأثیر می‌گذارد؟

سخت‌افزاری watchpoint بر عملکرد تأثیر نمی‌گذارد — وقفه در سطح پردازنده رخ می‌دهد. نرم‌افزاری (پس از پر شدن ثبات‌های سخت‌افزاری) اجرا را ۱۰–۵۰ بار کند می‌کند زیرا LLDB هر دستور نوشتن را بررسی می‌کند.

خلاصه

  • Watchpoint — نقطه مشاهده تغییر حافظه که با هر نوشتن در آدرس مشخص شده از هر نخ فعال می‌شود.
  • سخت‌افزاری watchpointها از ثبات‌های DWT پردازنده استفاده می‌کنند و اجرا را کند نمی‌کنند، اما به ۴–۸ ثبات محدود هستند.
  • LLDB از سه نوع watchpoint پشتیبانی می‌کند: روی متغیر، روی عبارت و روی آدرس خام حافظه.
  • شرطی watchpointها فقط هنگام برآورده شدن یک عبارت مشخص فعال می‌شوند — برای دیباگ تغییرات با فرکانس بالا ضروری است.
  • Watchpointها روی ویژگی‌های اشیاء و عناصر مجموعه‌ها با تخصیص مجدد حافظه نامعتبر می‌شوند.
  • Watchpointها بین جلسات ذخیره نمی‌شوند و با خروج متغیر از محدوده دید حذف می‌شوند.
  • Watchpoint بهترین انتخاب زمانی است که متغیر مشخص است اما محل تغییر آن ناشناخته است، به‌ویژه در کد چندنخی.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید