Watchpoint (gözlem noktası) — belirtilen bir değişkenin veya bellek bölgesinin değeri değiştiğinde program yürütmesini duraklatan bir hata ayıklama mekanizmasıdır. Bir kod satırına bağlı olan breakpoint'in aksine, watchpoint değişikliğin programın neresinde gerçekleştiğine bakılmaksızın veri değişikliklerini izler. Apple Developer Documentation'ya göre, watchpoint'ler veri yarışlarının, beklenmeyen özellik değişikliklerinin hata ayıklaması ve nesne yaşam döngüsü takibi için vazgeçilmezdir.
Önemli Noktalar
Watchpoint — belirtilen bir bellek adresindeki değer değiştiğinde program yürütmesini duraklatan bir hata ayıklayıcı mekanizmasıdır. Breakpoint belirli bir kod satırına ulaşıldığında tepki verirken, watchpoint belirli bir bellek hücresine yazma yapıldığında tepki verir — kodun hangi bölümünün yazmayı gerçekleştirdiğine bakılmaksızın. Bu, özellikle çok iş parçacıklı uygulamalarda beklenmeyen değişken değişikliklerini bulmak için onu vazgeçilmez kılar.
Çalışma prensibi işlemci donanım desteğine dayanır. Modern ARM yongaları (Apple Silicon, Qualcomm Snapdragon) 4 ila 8 donanım watchpoint kaydı sağlar. İşlemci, bir watchpoint'le eşleşen bir adrese yazma talimatı yürüttüğünde, hata ayıklayıcının yakaladığı bir donanım kesmesi oluşur. Donanım kayıtları tükendiğinde, LLDB yazılım moduna geçer — her yazma talimatını adım adım kontrol eder ve yürütmeyi onlarca kez yavaşlatır.
ARM Architecture Reference Manual'a göre, donanım watchpoint'leri Data Watchpoint and Trace (DWT) modülü seviyesinde çalışır ve yürütülebilir kodun değiştirilmesini gerektirmez. Yanıt süresi nanosaniye düzeyindedir ve ses veya video kare arabellekleri gibi veri işleme döngülerinde yüksek frekanslı değişken değişikliklerini bile izlemeye olanak tanır.
Watchpoint, hangi değişkenin değiştiğini bildiğiniz ancak nereden değiştiğini bilmediğiniz durumlarda vazgeçilmezdir. Tipik senaryolar: Bir UIView'in frame özelliği belirgin bir sebep olmadan değişir; arka plan iş parçacığındaki bir sayaç öngörülemez şekilde sıfırlanır; bir isLoading bayrağı ağ isteği tamamlanmadan önce değişir. Bu durumların her birinde, yazmanın gerçekleşebileceği tüm yerlere breakpoint koymak pratik değildir. Watchpoint sorunu tek bir komutla çözer.
Xcode ve LLDB üç tür watchpoint'i destekler: watchpoint set variable — yerel bir değişkeni izlemek için; watchpoint set expression — adres döndüren bir ifadeyi izlemek için; watchpoint set — ham bir bellek adresini izlemek için. Her türün kendi uygulama alanı vardır.
| Watchpoint türü | LLDB komutu | Kullanım |
|---|---|---|
| Değişken | watchpoint set variable -w write self.count | Yerel ve genel değişkenler, yapı özellikleri |
| İfade | watchpoint set expression -w write -- &self->mutex.lock | İşaretçi ile yapı alanları, dizinle dizi öğeleri |
| Adres | watchpoint set -w write 0x600000c4b80 | Önceki LLDB çıktısından belirli bellek adresi |
Xcode'da, Hata Ayıklama Alanı aracılığıyla bir watchpoint ayarlayabilirsiniz: bir breakpoint'te durun, Variables View panelinde istediğiniz değişkeni bulun, sağ tıklayın ve Watch Variable seçeneğini seçin. Xcode, doğru değişken adı ve bağlamıyla watchpoint set variable komutunu otomatik olarak yürütecektir. Bundan sonra hata ayıklayıcı her değer değişikliğinde duracaktır — konsola geçmeden hızlı hata ayıklama için kullanışlıdır. Ancak bu yöntem yalnızca değişken geçerli çerçevenin kapsamı içinde olduğu sürece çalışır.
func processItems(_ items: [String]) {
var index = 0
// GUI aracılığıyla index üzerinde watchpoint ayarla:
// burada dur, sağ tıkla → Watch Variable
for item in items {
index += 1
print("Öğe \(index): \(item)")
}
}
LLDB, konsoldan watchpoint'leri yönetmek için eksiksiz bir komut seti sağlar. Bu, GUI'den daha fazla kontrol sağlar: gözlem bölgesi boyutunu ayarlayabilir, tetikleme koşulları belirleyebilir, hesaplanmış ifadelerden elde edilen adreslerde watchpoint'ler oluşturabilir ve tetiklendiğinde otomatik olarak eylemler gerçekleştirebilirsiniz. Komut arayüzü, gözlem parametrelerini hızlıca değiştirmeyi gerektiren karmaşık senaryoların hata ayıklamasında özellikle kullanışlıdır.
watchpoint set variable komutu, kapsamı dikkate alarak bir değişken adı alır: Objective-C self özellikleri için self->_property, Swift için self.property kullanın. -w write parametresi yazma izlemeyi ayarlar, -w read — okuma izlemeyi (yalnızca bazı mimarilerde kullanılabilen bir mod), -s size — bölge boyutunu bayt cinsinden ayarlar. Bir watchpoint ayarladıktan sonra, listeyi watchpoint list komutuyla görüntüleyebilirsiniz.
(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'
Breakpoint'ler gibi, watchpoint'ler de koşullu tetiklemeyi destekler. -c parametresi Swift veya Objective-C'de bir koşul belirler. Örneğin, newValue > 1000 koşuluna sahip bir watchpoint, yalnızca yazılan değer bini aştığında duracaktır. Bu, saniyede binlerce değişiklik üreten döngüleri veya sensörleri hata ayıklarken kritiktir — aksi takdirde hata ayıklayıcı her değişiklikte durur ve çalışmayı imkansız hale getirir.
(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
// Değeri otomatik olarak günlüğe kaydet ve yürütmeye devam et
Objective-C ve Swift nesne özellikleri için watchpoint'lerin belirli bir özelliği — bir watchpoint, özellik adına değil, nesnenin belleğindeki ivar (örnek değişkeni) alanının adresine ayarlanır. Bu, her yeni nesne tahsisinde (örneğin, bir ViewController'ı yeniden oluştururken) bellek adresi değiştiği için watchpoint'in geçersiz hale geldiği anlamına gelir. Yeniden başlatmalar arasında bir özelliğin sürekli izlenmesi için, watchpoint'i nesne başlatma anında yeniden ayarlamanız gerekir.
Dizilerin ve sözlüklerin öğelerini izlemek, belirli bir öğenin adresinin hesaplanmasını gerektirir. Örneğin, bir dizinin üçüncü öğesini izlemek için watchpoint set expression -- &array[2] kullanın. Dizi, dahili arabelleğini yeniden tahsis ederse (kapasitenin ötesinde öğe eklerken), watchpoint geçersiz hale gelir — LLDB bir Watchpoint 1 has an invalid address hatası bildirir. Bu gibi durumlarda, koleksiyon boyutunu değiştirdikten sonra watchpoint'i yeniden ayarlamanız gerekir.
(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
Objective-C'de, objc_object yapısındaki retainCount alanına bir watchpoint ayarlayarak bir nesnenin retain count değerini izleyebilirsiniz. LLDB bunu watchpoint set expression -w write -- (int*)[object retainCount] aracılığıyla yapar. Ancak ARC (Otomatik Referans Sayımı) olan Swift nesneleri için retain count'a doğrudan erişilemez — bunun yerine sızıntı analizi için Instruments veya Memory Graph Debugger'ı kullanın. Apple'a göre, retain count üzerindeki watchpoint'ler yalnızca ARC optimizasyonu devre dışı bırakılmış Debug yapılarında çalışır.
Watchpoint'lerin dikkate alınması gereken birkaç önemli sınırlaması vardır. Başlıca — donanım watchpoint'lerinin sayısı ARM mimarisinde 4–8 kayıt ve x86'da 4'e kadar sınırlıdır. Tüm donanım kayıtları meşgul olduğunda, LLDB yazılım watchpoint moduna geçer: bir istisna oluşturmak için izlenen aralıktaki her yazma talimatını değiştirir. Bu, yürütmeyi 10–50 kat yavaşlatır, bu nedenle pratikte aynı anda 2–3'ten fazla aktif watchpoint kullanılmaması önerilir.
İkinci sınırlama — bellek yeniden tahsisinde watchpoint'lerin geçersiz kılınması. Çöp toplama veya ARC tetiklendiğinde ve bir nesne bellekte taşındığında (yığın sıkıştırmalı dillerde), watchpoint adresi yanlış hale gelir. Swift ve Objective-C'de ARC nesneleri taşımaz, ancak dizi ve dize yeniden tahsisi aynı etkiye neden olur. LLDB, Watchpoint N address (0x...) doesn’t contain a valid allocation mesajıyla bu konuda uyarır.
Üçüncü sınırlama — değişken görünürlüğü. Yerel bir değişkendeki watchpoint, yalnızca bu değişken geçerli yığın çerçevesinin kapsamı içinde olduğu sürece çalışır. İşlev sona erdiğinde, watchpoint otomatik olarak kaldırılır. Genel değişkenleri veya uzun ömürlü nesnelerin alanlarını izlemek için, watchpoint watchpoint delete ile açıkça silinene veya işlem sonlanana kadar kalıcı olur.
(lldb) watchpoint delete 1
1 watchpoints deleted.
(lldb) watchpoint delete # Tüm watchpoint'leri sil
2 watchpoints deleted.
(lldb) watchpoint disable 1 # Geçici olarak devre dışı bırak
(lldb) watchpoint enable 1 # Yeniden etkinleştir
ARM'a göre, Apple Silicon (M1–M4) üzerindeki watchpoint'ler 1 ila 8 bayt arasında izlenen bölge boyutunu destekler. 8 bayttan büyük yapıları izlemek için, her alana birden çok watchpoint ayarlamanız gerekir. Bu, CGRect (16 bayt) veya UIEdgeInsets (16 bayt) gibi karmaşık veri yapılarının hata ayıklamasında önemlidir.
Sıkça Sorulan Sorular
Breakpoint bir kod satırına bağlıdır — bu satıra ulaşıldığında durur. Watchpoint bir bellek adresine bağlıdır — programın herhangi bir yerinden bu adrese yazma yapıldığında durur. Watchpoint “kimin değeri değiştirdiğini” arar, breakpoint “bu satırda ne olduğunu” arar.
ARM'de (Apple Silicon dahil) 4–8 donanım watchpoint'i. Bunun aşılması watchpoint'i yazılım moduna geçirir ve yürütmeyi 10–50 kat yavaşlatır. Aynı anda 2–3'ten fazla aktif watchpoint kullanılmaması önerilir.
Watchpoint'ler hata ayıklama oturumları arasında korunmaz. Her yeni başlatmada, bellek adresleri değişir ve watchpoint'in yeniden ayarlanması gerekir. İstisna, sabit adresli genel değişkenlerdeki watchpoint'lerdir.
Evet, ancak watchpoint özelliğin ivar'ına (destek deposu) ayarlanır, özelliğin kendisine değil. Swift'te watchpoint set variable self.property kullanın — LLDB, özellik adına göre ilgili ivar'ı otomatik olarak bulacaktır.
Donanım watchpoint'leri performansı etkilemez — kesinti işlemci düzeyinde gerçekleşir. Yazılım watchpoint'leri (donanım kayıtları tükendiğinde) yürütmeyi 10–50 kat yavaşlatır, çünkü LLDB her yazma talimatını kontrol eder.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun