Vid ett eller annat tillfälle kommer du att köra in i en krasch orsakad av EXC_BAD_ACCESS. I det här snabba tipset lär du dig vad EXC_BAD_ACCESS är och vad det orsakas av. Jag kommer också att ge dig några tips för att fixa fel som orsakas av EXC_BAD_ACCESS.
När du förstår den bakomliggande orsaken till EXC_BAD_ACCESS förstår du bättre dess kryptiska namn. Det finns en enkel förklaring och en mer teknisk förklaring. Låt oss börja med den enkla förklaringen först.
När du stöter på EXC_BAD_ACCESS betyder det att du skickar ett meddelande till ett objekt som redan har släppts. Detta är det vanligaste scenariot, men det finns undantag som vi diskuterar på ett ögonblick.
Den tekniska förklaringen är lite mer komplex. I C och Objective-C hanterar du ständigt pekare. En pekare är inget annat än en variabel som lagrar minnesadressen till en annan variabel. När du skickar ett meddelande till ett objekt måste pekaren som pekar på det objekt du skickar meddelandet vara dereferenced. Det betyder att du tar minnesadressen som pekaren pekar på och åtkomst till värdet av det här minnesblocket.
När det här minnesblocket inte längre är mappat för din ansökan eller, sätt på annat sätt, det här minnesblocket inte används för det du tycker är det används, är det inte längre möjligt att komma åt den biten av minne. När detta händer skickar kärnan ett undantag (EXC), vilket indikerar att din ansökan inte kan komma åt det här minnesblocket (Dålig åtkomst).
Sammanfattningsvis innebär det att du försöker skicka ett meddelande till ett block av minne som inte kan utföra meddelandet när du stöter på EXC_BAD_ACCESS..
I vissa fall orsakas emellertid EXC_BAD_ACCESS av en korrupt pekare. När din ansökan försöker avleda en korrupt pekare kastas ett undantag av kärnan.
Felsökning EXC_BAD_ACCESS kan vara knepigt och frustrerande. Men nu när EXC_BAD_ACCESS inte längre är en gåta för dig, borde det vara mindre skrämmande.
Det första du behöver förstå är att din ansökan inte nödvändigtvis kraschar när minnesblocket inte längre är tillgängligt för din ansökan. Det gör det ofta så svårt att felsöka EXC_BAD_ACCESS.
Detsamma gäller för korrupta pekare. Din ansökan kommer inte att krascha eftersom en pekare gick korrupt. Det kommer inte att krascha om du skickar en korrupt pekare runt i din ansökan. När din ansökan försöker härleda den korrupta pekaren går det dock fel.
Medan zombier har stigit i popularitet de senaste åren har de funnits i Xcode i mer än ett decennium. Namnet zombie kan låta lite dramatisk, men det är faktiskt ett bra namn för funktionen som ska hjälpa oss att felsöka EXC_BAD_ACCESS. Låt mig förklara hur det fungerar.
I Xcode kan du aktivera zombieobjekt, vilket innebär att deallokerade objekten hålls kvar som zombies. Förskjutna objekt hålls annorlunda för felsökningsändamål. Det finns ingen magi involverad. Om du skickar ett meddelande till ett zombieobjekt, kommer din ansökan fortfarande att krascha som ett resultat av EXC_BAD_ACCESS.
Varför är det här användbart? Det som är svårt att felsöka EXC_BAD_ACCESS är att du inte vet vilket objekt din ansökan försökte få åtkomst till. Zombieobjekt löser detta problem i många fall. Genom att hålla deallokerade objekten levande kan Xcode berätta vilket objekt du försökte komma åt, vilket gör sökningen efter problemet så mycket lättare.
Att aktivera zombies i Xcode är väldigt enkelt. Observera att det kan skilja sig beroende på vilken version av Xcode du använder. Följande tillvägagångssätt gäller Xcode 6 och 7. Klicka på det aktiva schemat längst upp till vänster och välj Redigera schema.
Välj Springa till vänster och öppna Diagnostik fliken längst upp. För att aktivera zombieobjekt, markera kryssrutan märkt Aktivera zombieobjekt.
Om du nu går in i EXC_BAD_ACCESS, kommer utmatningen i Xcodes Console att ge dig en mycket bättre uppfattning om var du ska börja din sökning. Ta en titt på följande exempel på utdata.
2015-08-12 06: 31: 55.501 Debug [2371: 1379247] - [ChildViewController respondsToSelector:] meddelande skickat till deallokerat instans 0x17579780
I det ovanstående exemplet säger Xcode oss att ett meddelande om respondsToSelector:
skickades till ett zombieobjekt. Zombieobjektet är dock inte längre en förekomst av ChildViewController
klass. Minnesblocket som tidigare tilldelades ChildViewController
Instans är inte längre mappad för din ansökan. Detta borde ge dig en ganska bra bild av vad orsaken till problemet är.
Tyvärr kommer zombieobjekt inte att kunna spara din dag för varje krasch orsakad av EXC_BAD_ACCESS. Om zombieobjekt inte gör tricket, så är det dags för någon riktig analys.
Om zombieobjekt inte löser ditt problem, kan grundorsaken vara mindre trivial. I så fall måste du titta närmare på koden som körs när din ansökan kraschar. Detta kan vara besvärligt och tidskrävande.
För att hjälpa dig att hitta problem i din kodbas kan du be Xcode att analysera din kod för att hjälpa dig att hitta problematiska områden. Observera att Xcode analyserar ditt projekt, vilket innebär att det kommer att påpeka varje potentiellt problem det möter.
För att berätta Xcode för att analysera ditt projekt, välj Analysera från Xcode s Produkt menyn eller tryck på Skift-kommando-B. Det kommer att ta Xcode några ögonblick, men när det är klart bör du se en lista med problem i Issue Navigator till vänster. Problem som hittats av analysen är markerade i blått.
När du klickar på ett problem tar Xcode dig till koden av koden som behöver din uppmärksamhet. Observera att Xcode bara gör ett förslag. I vissa fall är det möjligt att problemet inte är relevant och inte behöver fixas.
Om du inte hittar felet som orsakar EXC_BAD_ACCESS är det viktigt att noggrant granska varje problem Xcode som hittades under analysen av ditt projekt.
EXC_BAD_ACCESS är en vanlig frustration bland utvecklare och det är något som är inneboende för manuell minneshantering. Problem med minnehantering har blivit mindre frekventa sedan introduktionen av ARC (Automatic Reference Counting), men de har inte försvunnit.