2009-01-22 13 views
6

Hier ist mein Fall: Ich habe eine Tabellenansicht, die Kontakte zeigt. Schaltfläche Hinzufügen in der Navigationsleiste wird zum Laden einer anderen Ansicht für die Dateneingabe verwendet. Diese neue Ansicht enthält Bilder im Tabellenheader, und jede Tabellenzelle hat entweder ein UITextField oder ein UITextView. Wenn ich Abbrechen drücke, wird die Ansicht ausgeblendet und der Speicher freigegeben.iPhone Entwicklung - EXC_BAD_ACCESS Fehler ohne Stack-Trace

Hier ist mein Problem: Wenn ich die Schaltfläche „Hinzufügen“ Schnittstelle zu öffnen, einen Wert in einem der UITextField oder UITextView liefern, und klicken Sie auf „Abbrechen“, um zurück zu der übergeordneten Ansicht zu gehen, erhalte ich eine EXC_BAD_ACCESS Fehler. Wenn ich es nachverfolg, ruft der "Add Controller" dealloc ordnungsgemäß, aber nach dem [Super Dealloc] wenn ich fortfahren drücken, wird dieser Fehler ausgelöst. Nur das, keine Spur, obwohl ich NSZombieEnabled verwende. Wenn ich den Code mit Instrumenten laufen, bekomme ich keine Fehler :(

Ich hoffe, dass ich bei der Erklärung der Frage klar bin. Alle Hinweise? Vielen Dank.

+0

Das Problem verschwindet magisch, wenn ich entfernen [Tableview release] von meinem "Kontakt hinzufügen" Dealloc-Methode der Controller-Klasse. Aber ich sollte das TableView-Objekt freigeben, richtig? Obwohl ich Nib-Datei verwende - und tableView ein 'IBOutlet' gemacht habe. – Mustafa

+1

Nein, sollten Sie nicht. Die zu beachtende Regel lautet: "Wenn Sie sie nicht explizit zugewiesen, kopiert oder behalten haben, geben Sie sie nicht explizit frei." –

Antwort

8

Die häufigste Ursache für diesen Fehler ist Wenn Sie ein Objekt freigeben und ein anderer Mechanismus versucht, auf sie zuzugreifen/sie später wieder freizugeben/loszulassen

Immer wenn ich einen Fehlerbericht von EXC_BAD_ACCESS erhalte, ist meine erste Empfehlung, den Code durchzugehen, um festzustellen, welche Zeile ihn verursacht. und dann nach expliziten [object release] Aufrufen zu suchen, die auf dieses Objekt verweisen, und sie einzeln auskommentieren, um herauszufinden, wo Sie möglicherweise einen Fehler gemacht haben (und natürlich t Das Objekt wird später ordnungsgemäß freigegeben.)

Wenn die Linie nicht hilft, herauszufinden, welche Objekte das Problem verursachen, beginnen Sie, durch Ihre [object release] Aufrufe zu sehen, und stellen Sie sicher, dass Sie Objekte nicht versehentlich zu oft freigeben oder freigeben Objekte, die du nicht besitzt.

Dies auf eine gute allgemeine Richtlinie führt in Bezug auf release in Objective-C:

Wenn Sie ein Objekt besitzen (zuweisen oder sie behalten), lassen Sie es. Wenn Sie es nicht besitzen (über die Convenience-Methode oder jemand anders zugewiesen), geben Sie es nicht frei.

(Via Memory Management with Objective C/Cocoa/iPhone, die auch einige gute Tipps hat.)

1

Die Faustregel ist, dass alles, was Sie erstellen, müssen Sie (Retain/Release) verwalten. Alles, was aus einer NIB kommt, sollte generell nicht im Code veröffentlicht werden.

3

Setzen Sie die [Super Dealloc] als letzte Anweisung der Klasse Dealloc-Methode. Dieses Verhalten tritt auf, wenn Sie die Superklasse zuerst freigeben.

6

Obwohl dies meist auf falsch verwaltetem Speicher beruht, kann dies aus anderen Gründen passieren (und schwieriger zu debuggen als einfach NSZombieEnabled einzuschalten). Wenn Sie beispielsweise nicht die korrekte Anzahl von Argumenten an eine Formatzeichenfolge übergeben (d. H. Während Sie ein anderes Problem mit NSLog debuggen), könnte dies dazu führen, dass auch bei allen aktivierten Debugging-Argumenten keine Stack-Trace ausgeführt wird. Glücklicherweise können Sie GDB innerhalb von Xcode zu restore the stack trace to a previous state verwenden.

In der GDB-Konsole sollten Sie die Anweisung sehen, die Ihr Programm abgestürzt ist. Suchen Sie die letzte erfolgreiche Rückgabeanweisung vor der fehlgeschlagenen Anweisung.Es soll wie folgt aussehen:

je 0x986cef35 <objc_msgSend+117> 

Hinweis des Hex-Wert und führen Sie die folgend in GDB:

set $eip = 0x986cef35 
stepi 
where 

Sie sollen (hoffentlich) einen informativen Stack-Trace jetzt.

Source (gleiche wie der Link oben)

+0

Die [link] (http://www.mulle-kybernetik.com/weblog/2010/07/exc_bad_access_and_no_stack_tr.html) funktioniert nicht. Hier ist das [aktualisiert] (http://www.mulle-kybernetik.com/weblog/2010/exc_bad_access_and_no_stack_tr.html) eins – BLC

1

Vorstehende Angaben, dass Sie NIB Objekte von Apple wieder nicht loslassen sollen: siehe here, wo es heißt, dass Objekte, für die Sie eine Steckdose haben in dealloc freigegeben werden sollen Außerdem sollten Sie sicherstellen, dass die Objektreferenz anschließend auf nil gesetzt wird.

Haftungsausschluss: Ich bin ein iPhone-Programmierer Neuling, obwohl schon seit langem programmiert.

2

Cameron Spickerts Antwort ist etwas veraltet, da Xcode jetzt lldb anstelle von gdb verwendet. Der Link zum Quellartikel ist ebenfalls tot.

Das gleiche kann nicht einfach mit dem folgenden LLDB Befehl:

(lldb) thread backtrace 

Diese bt für den aktuellen Thread zeigen. Wenn Sie den Thread ändern möchten, aus dem Sie die bt erhalten möchten, wählen Sie den Rahmen und bekommen es wie folgt aus:

(lldb) thread list 
(lldb) thread select 2 
(lldb) thread backtrace 

Wenn Sie das genaue Verhalten von Cameron Spickert Antwort replizieren möchten, verwenden Sie die folgenden Befehle ein:

(lldb) expr unsigned int $eip = 0x1979c81d4 
(lldb) stepi 
(lldb) thread backtrace 

Source 1

Source 2