2009-07-29 2 views
6

Ich habe ein Retain/Release-Problem. Meine Ansicht ist ziemlich kompliziert, deshalb habe ich NSZombieEnabled auf YES gesetzt und versuche herauszufinden, welches Objekt mich wirklich betrübt. Um diesen Prozess zu beschleunigen, frage ich mich, ob es Hinweise oder Tricks gäbe, um die Zombies zurück zum Grab zu bringen, aus dem sie ihren Weg (Entschuldigung, Müssen) oder zurück zu dem Objekt gegraben haben, mit dem sie verbunden sind? Die kryptische Konsolennachricht scheint nicht viel Einblick zu bieten:NSZombies essen das Gehirn meiner App!

NSInvocation: warning: object 0x1076850 of class '_NSZombie_CALayer' does not implement methodSignatureForSelector: -- trouble ahead 

Ich habe keine Selektoren genannt "Ärger voraus".

bearbeiten - inklusive Stack Trace:

#0 0x3026e017 in ___forwarding___ 
#1 0x3024a0a2 in __forwarding_prep_0___ 
#2 0x302042e8 in CFRelease 
#3 0x00c4fc31 in CALayerUpdateSublayers 
#4 0x00c4e173 in -[CALayer dealloc] 
#5 0x00c4000e in CALayerRelease 
#6 0x00c48dad in CALayerFreeTransaction 
#7 0x00c410b8 in CA::Transaction::commit 
#8 0x00c492e0 in CA::Transaction::observer_callback 
#9 0x30245c32 in __CFRunLoopDoObservers 
#10 0x3024503f in CFRunLoopRunSpecific 
#11 0x30244628 in CFRunLoopRunInMode 
#12 0x32044c31 in GSEventRunModal 
#13 0x32044cf6 in GSEventRun 
#14 0x309021ee in UIApplicationMain 
#15 0x00001eb4 in main at main.m:14 

Edit 2: ObjectAlloc

die Speicheradresse in Frage in ObjectAlloc Looking up finde ich zwei Spiele:

# Address  Category   Creation Time  Size Responsible Library Responsible Caller 
0 0x1076980 GeneralBlock-48 00:11.470  48  QuartzCore -[CALayer setDelegate:] 
1 0x1076980 CALayer   00:11.552  48  UIKit  -[UIView _createLayerWithFrame:] 

in Graben # 0 GeneralBlock-48:

# Category  Event Type Timestamp Address Size Responsible Library Responsible Caller 
0 GeneralBlock-48 Malloc  00:11.470 0x1076980 48 QuartzCore -[CALayer setDelegate:] 
1 GeneralBlock-48 Free  00:11.551 0x1076980 -48 QuartzCore -[CALayer addAnimation:forKey:] 
2 CALayer   Malloc  00:11.552 0x1076980 48 UIKit -[UIView _createLayerWithFrame:] 

Graben in # 1 CALayer:

# Category  Event Type Timestamp Address Size Responsible Library Responsible Caller 
0 GeneralBlock-48 Malloc  00:11.470 0x1076980 48 QuartzCore -[CALayer setDelegate:] 
1 GeneralBlock-48 Free  00:11.551 0x1076980 -48 QuartzCore -[CALayer addAnimation:forKey:] 
2 CALayer   Malloc  00:11.552 0x1076980 48 UIKit -[UIView _createLayerWithFrame:] 

Nun, ich sehe jetzt in tiefer, dass die Bohrungen entweder # 0 oder # 1 zeigt genau die gleiche Information. Ich nehme an, dass sollte die Fehlerbehebung in zwei Hälften geschnitten ... aber ich bin immer noch ratlos ...

+1

Haben Sie versucht, Schrotflinten in Ihre Anwendung zu programmieren? – Sneakyness

+1

Ich nahm eine Abkürzung und versuchte den Holzpfahl ... ach, das funktioniert nur auf NSVampires :-( – Meltemi

+0

+1 für die Details der Frage, und der interessante Titel: D –

Antwort

6

Ich glaube, das Backtrace ist genau der Punkt, wo der Zombie gemeldet wird. Dieses Backtrace gibt normalerweise keine Informationen darüber, was den Absturz verursacht. Es ziemlich viel sagt Ihnen, nur die Art und die Adresse des Objekts, das über freigegeben wird.

Eine Technik, die ich oft wie diese auf der Spur über Releases verwenden Instruments ObjectAlloc verwenden, um alle behalten und gibt zu verfolgen. Suchen Sie in ObjectAlloc nach der Adresse für das Objekt, das zu viel freigegeben wurde, und listen Sie dann alle Retain/Release-Aufrufe auf, und versuchen Sie anschließend, jedes Retain mit einem Release auszugleichen. Sobald Sie eine Freigabe gefunden haben, ohne dass eine Übereinstimmung vorhanden ist, haben Sie das Problem gefunden.

+0

Tut mir leid, aber wie "listen Sie alle Retain/Release Calls" in Instruments auf? – Meltemi

+1

Klicken Sie in der Tabellenansicht mit allen Zuordnungen auf den Pfeil neben "* Alle Zuordnungen *". Suche nach der Adresse des Zombies CALayer (du kannst es in das Suchfeld unten einfügen). Klicken Sie auf den Pfeil neben dieser Adresse. Auf dieser Adresse wird eine Liste aller malloc/free/retain/release-Anrufe angezeigt. Öffnen Sie die Seitenleiste, um die Stack-Ablaufverfolgung für jeden Aufruf anzuzeigen. – kperryua

+0

Danke! Hilfreich! Aber wenn ich mit ObjectAlloc laufe, tauchen die NSZombies nicht auf. Also kann ich diese Adresse nicht mit dem vergleichen, was in der Liste steht. Ich glaube, dass Instrumente sowohl den Debugger als auch die Konsole von XCode umgehen. Ah, ich glaube, ich habe gerade diesen Teil der Frage beantwortet: Schau in Console.app und nicht in XCodes Konsole ... – Meltemi

2

Eine schnelle Sache, die Sie tun können, ist einen symbolischen Haltepunkt auf objc_exception_throw setzen. Dadurch wird Ihr Programm angehalten, sobald eine Ausnahme ausgelöst wird. Dies kann nicht helfen, genau zu finden, die CALayer Ihnen Kummer gibt, aber es sollte Ihnen helfen, die allgemeine Umgebung zu finden, wo es genannt wird.

+0

vereinbart, Sie müssen genau wissen, wann dies geschieht. –

+0

Ich hatte den Breakpoint objc_exception_throw aktiviert, aber es ist für mich genauso kryptisch. Ich habe es oben gepostet. – Meltemi

+0

Was ist der Kontext für diesen Fehler? Was machst du mit deinem Programm, um es in Brand zu setzen? Von der Stack-Ablaufverfolgung aus sieht es so aus, als ob sie am Ende einer CA-Transaktion stattfindet, was bedeutet, dass es am Ende einer Animation sicher ist. Wird eine Animation ausgelöst? Wenn ja, um welche Schichten handelt es sich? Stellen Sie sicher, dass Sie diejenigen behalten, die Sie wieder verwenden möchten? – Alex

2

"Ärger voraus" ist Teil der Warnung, nicht der Selektor. Die Warnung selbst kommt von NSInvocation, aber die Tatsache, dass sie "class_NSZombie_CALayer" erwähnt, bedeutet, dass etwas versucht, mit einem CALayer zu arbeiten, der deallociert wurde.

Der Stack-Trace zeigt an, dass dies geschieht, wenn ein Layer versucht, seine Sublayer freizugeben.

Insgesamt bedeutet dies, dass die Schicht eine Unterschicht freigesetzt hat, die irgendwo in Ihrem Code über freigegeben wurde. Überprüfen Sie Ihre Speicherverwaltung von CALayers oder versuchen Sie Clang Static Analyzer.