Watchpoint (observationspunkt) — en debugmekanism som pausar programexekveringen när värdet på en angiven variabel eller minnesområde ändras. Till skillnad från en breakpoint, som är bunden till en kodrad, spårar watchpoint dataförändringar oavsett i vilken del av programmet ändringen skedde. Enligt Apple Developer Documentation är watchpoints oumbärliga vid felsökning av datakapplöpningar, oväntade egenskapsändringar och spårning av objekts livscykel.
Huvudpunkter
Watchpoint — en debugger-mekanism som pausar programexekveringen när värdet på en angiven minnesadress ändras. Medan en breakpoint reagerar på att en specifik kodrad nås, reagerar en watchpoint på skrivning till en specifik minnescell — oavsett vilken koddel som utförde skrivningen. Detta gör den oumbärlig vid sökning efter oväntade variabeländringar, särskilt i flertrådade applikationer.
Funktionsprincipen bygger på processorns hårdvarustöd. Moderna ARM-chipp (Apple Silicon, Qualcomm Snapdragon) tillhandahåller 4 till 8 hårdvaruregister för watchpoints. När processorn utför en skrivinstruktion på en adress som matchar en watchpoint uppstår ett hårdvaruavbrott som debugger fångar upp. Om hårdvaruregisterna tar slut växlar LLDB till mjukvaruläge — det kontrollerar varje skrivinstruktion steg för steg, vilket saktar ner exekveringen tiotals gånger.
Enligt ARM Architecture Reference Manual arbetar hårdvaru-watchpoints på nivån av Data Watchpoint and Trace (DWT)-modulen och kräver ingen modifiering av exekverbar kod. Reaktionstiden vid aktivering är i nanosekundklassen, vilket möjliggör spårning även av högfrekventa variabeländringar i databehandlingsloopar som ljudbuffertar eller videoramar.
Watchpoint är oumbärlig när du vet vilken variabel som ändras men inte vet varifrån. Typiska scenarier: värdet på egenskapen frame i UIView ändras utan synbar anledning; en räknare i en bakgrundstråd återställs oförutsägbart; flaggan isLoading växlar innan nätverksbegäran har slutförts. I vart och ett av dessa fall är det opraktiskt att placera breakpoints på alla ställen där skrivning kan ske. Watchpoint löser problemet med ett enda kommando.
Xcode och LLDB stöder tre typer av watchpoints: watchpoint set variable — för observation av en lokal variabel; watchpoint set expression — för observation av ett uttryck som returnerar en adress; watchpoint set — för observation av en rå minnesadress. Varje typ har sitt tillämpningsområde.
| Watchpoint-typ | LLDB-kommando | Användning |
|---|---|---|
| Variabel | watchpoint set variable -w write self.count | Lokala och globala variabler, strukturegenskaper |
| Uttryck | watchpoint set expression -w write -- &self->mutex.lock | Strukturfält via pekare, arrayelement efter index |
| Adress | watchpoint set -w write 0x600000c4b80 | Specifik minnesadress från tidigare LLDB-utdata |
I Xcode kan en watchpoint installeras via Debug Area: stanna vid en breakpoint, hitta önskad variabel i panelen Variables View, högerklicka och välj Watch Variable. Xcode utför automatiskt kommandot watchpoint set variable med korrekt variabelnamn och kontext. Därefter stoppar debugger vid varje värdeändring — bekvämt för snabb felsökning utan att växla till konsolen. Denna metod fungerar dock bara så länge variabeln befinner sig inom den aktuella ramens synlighetsområde.
func processItems(_ items: [String]) {
var index = 0
// Ställ in watchpoint på index via GUI:
// stanna här, högerklicka → Watch Variable
for item in items {
index += 1
print("Item \(index): \(item)")
}
}
LLDB tillhandahåller en fullständig uppsättning kommandon för att hantera watchpoints från konsolen. Detta ger större kontroll än GUI: du kan ange observationsområdets storlek, ställa in ett aktiveringsvillkor, skapa watchpoints på adresser som erhållits från beräknade uttryck och automatiskt utföra åtgärder vid aktivering. Kommandoradsgränssnittet är särskilt användbart vid felsökning av komplexa scenarier där snabb ändring av observationsparametrar krävs.
Kommandot watchpoint set variable accepterar variabelnamnet med hänsyn till synlighetsområdet: för self-egenskaper i Objective-C använd self->_property, för Swift — self.property. Parametern -w write ställer in spårning av skrivning, -w read — läsning (läge endast tillgängligt på vissa arkitekturer), -s size — områdets storlek i byte. Efter installation av en watchpoint kan listan visas med kommandot watchpoint list.
(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'
Precis som breakpoints stöder watchpoints villkorlig aktivering. Parametern -c anger ett villkor i Swift eller Objective-C. Till exempel stannar en watchpoint med villkoret newValue > 1000 endast när det skrivna värdet överstiger tusen. Detta är kritiskt vid felsökning av loopar eller sensorer som genererar tusentals ändringar per sekund — annars skulle debugger stanna vid varje ändring, vilket gör arbetet omöjligt.
(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
// Logga automatiskt värdet och fortsätt exekveringen
Särdraget hos watchpoints för Objective-C och Swift objektegenskaper — watchpoint installeras inte på egenskapsnamnet utan på adressen till fältet ivar (instansvariabel) i objektets minne. Detta innebär att vid varje ny allokering av objektet (till exempel när en ViewController återskapas) blir watchpoint ogiltig eftersom minnesadressen har ändrats. För kontinuerlig observation av en egenskap över omstarter måste watchpoint återinstalleras vid objektets initieringstillfälle.
Observation av element i arrayer och ordböcker kräver beräkning av adressen till det specifika elementet. För att observera det tredje elementet i en array, använd till exempel watchpoint set expression -- &array[2]. Om arrayen omallokerar sin interna buffert (vid tillägg av element utöver kapaciteten) blir watchpoint ogiltig — LLDB rapporterar felet Watchpoint 1 has an invalid address. I sådana fall måste watchpoint återinstalleras efter ändring av samlingens storlek.
(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
I Objective-C kan du spåra ett objekts retain count genom att installera en watchpoint på fältet retainCount i strukturen objc_object. LLDB utför detta via watchpoint set expression -w write -- (int*)[object retainCount]. För Swift-objekt med ARC (Automatic Reference Counting) är retain count dock inte direkt tillgängligt — använd istället Instruments eller Memory Graph Debugger för minnesläcksanalys. Enligt Apple fungerar watchpoints på retain count endast i Debug-byggen med avaktiverad ARC-optimering.
Watchpoints har ett antal begränsningar som måste beaktas. Den främsta — antalet hårdvaru-watchpoints är begränsat till 4–8 register på ARM-arkitektur och upp till 4 på x86. När alla hårdvaruregister är upptagna växlar LLDB till mjukvaru-watchpoint-läge: det modifierar varje skrivinstruktion i det spårade intervallet för att generera ett undantag. Detta saktar ner exekveringen 10–50 gånger, därför rekommenderas i praktiken att inte använda mer än 2–3 aktiva watchpoints samtidigt.
Den andra begränsningen — ogiltighet av watchpoints vid minnesomallokering. Vid körning av garbage collector eller ARC, när ett objekt flyttas i minnet (i språk med heap-kompaktering), blir watchpoint-adressen felaktig. I Swift och Objective-C flyttar ARC inte objekt, men omallokering av arrayer och strängar leder till samma effekt. LLDB varnar om detta med meddelandet Watchpoint N address (0x...) doesn't contain a valid allocation.
Den tredje begränsningen — variablers synlighet. En watchpoint på en lokal variabel fungerar bara så länge variabeln befinner sig inom den aktuella stackramens synlighetsområde. Så snart funktionen avslutas tas watchpoint automatiskt bort. För observation av globala variabler eller fält hos långlivade objekt behålls watchpoint tills explicit borttagning via watchpoint delete eller tills processen avslutas.
(lldb) watchpoint delete 1
1 watchpoints deleted.
(lldb) watchpoint delete # Ta bort alla watchpoints
2 watchpoints deleted.
(lldb) watchpoint disable 1 # Tillfälligt inaktivera
(lldb) watchpoint enable 1 # Aktivera igen
Enligt ARM stöder watchpoints på Apple Silicon (M1–M4) en spårad områdesstorlek från 1 till 8 byte. För observation av strukturer större än 8 byte måste flera watchpoints installeras på varje fält. Detta är viktigt vid felsökning av komplexa datastrukturer som CGRect (16 byte) eller UIEdgeInsets (16 byte).
Vanliga frågor
Breakpoint är bunden till en kodrad — stannar när den nås. Watchpoint är bunden till en minnesadress — stannar vid skrivning till den adressen från valfri del av programmet. Watchpoint söker efter ”vem som ändrar värdet”, breakpoint efter ”vad som händer på denna rad”.
4–8 hårdvaru-watchpoints på ARM (inklusive Apple Silicon). Överskridning växlar watchpoint till mjukvaruläge, vilket saktar ner exekveringen 10–50 gånger. Rekommenderas högst 2–3 aktiva watchpoints samtidigt.
Watchpoints sparas inte mellan felsökningssessioner. Vid varje ny start ändras minnesadresserna och watchpoint måste installeras på nytt. Undantag — watchpoints på globala variabler med fast adress.
Ja, men watchpoint installeras på ivar (bakomliggande lagring) för egenskapen, inte på egenskapen själv. I Swift använd watchpoint set variable self.property — LLDB hittar automatiskt motsvarande ivar baserat på egenskapens namn.
Hårdvaru watchpoint påverkar inte prestandan — avbrottet sker på processornivå. Mjukvaru (när hårdvaruregisterna tar slut) saktar ner exekveringen 10–50 gånger eftersom LLDB kontrollerar varje skrivinstruktion.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också