Wie finde ich die Ursache für einen "doppelt freien" Malloc-Fehler?

80

Ich programmiere eine Anwendung in Objective-C und erhalte folgende Fehlermeldung:

MyApp (2121,0xb0185000) malloc: *** Fehler für Objekt 0x1068310: double free
*** Setzen Sie einen Haltepunkt in malloc_error_break zum Debuggen

Es passiert, wenn ich einen NSAutoreleasePool veröffentliche und nicht herausfinden kann, welches Objekt ich zweimal freigebe.

Wie setze ich seinen Haltepunkt?

Gibt es eine Möglichkeit zu wissen, was dieses "Objekt 0x1068310" ist?

Gonso
quelle
3
Vielleicht möchten Sie diesen Beitrag auch mit dem iPhone markieren, um weitere Personen zu gewinnen
Benny Wong
4
"IPhone" -Tag zugunsten anderer relevanterer Tags entfernt.
Quinn Taylor
3
Ich kann mir nicht vorstellen, warum dieser iPhone-Frage das iPhone-Tag fehlen würde. Es müssen mehr Leute "iPhone" folgen als einige dieser anderen Tags wie "Autorelease". Wenn Sie "Autorelease" finden möchten, suchen Sie danach und folgen dem Tag nicht. Also habe ich "iPhone" wieder eingesetzt.
Nosredna
6
Der Grund, warum ich das "iPhone" -Tag entfernt habe, ist, dass nichts über die Frage spezifisch für das iPhone ist. Der einzige Link ist, dass er in einer iPhone-App auftritt, aber genau der gleiche Fehler kann in jeder C- oder Objective-C-Anwendung auftreten. Ich erwarte nicht, dass Leute, die dem iPhone folgen, sich gelegentlich dafür interessieren - vielmehr sind es Leute, die nach Dingen wie "double free" oder "malloc_error_break" suchen, und wenn sie "iPhone" einwerfen, wird es immer noch auftauchen . Lassen Sie uns nicht über Tags streiten, aber denken Sie daran, dass die Leute, die antworten, vielleicht wissen, wo die Frage am besten hingehört.
Quinn Taylor
3
Diese Frage ist zumindest kakaospezifisch. Wenn das iPhone-Tag beleidigt ist, wie wäre es mit einem Kakao-Tag? Die offensichtliche Absicht gilt für Objective-C für Kakao in XCode. Nicht Objective-C unter Windows oder Linux oder außerhalb des XCode-Kontexts.
Runako

Antworten:

38

Sie werden herausfinden, was das Objekt ist, wenn Sie den Debugger einbrechen. Schauen Sie einfach im Call Stack nach und Sie werden feststellen, wo Sie ihn freigeben. Das wird Ihnen sagen, um welches Objekt es sich handelt.

Der einfachste Weg, den Haltepunkt festzulegen, ist:

  1. Gehen Sie zu Ausführen -> Anzeigen -> Haltepunkte ( ALT- Command- B)
  2. Scrollen Sie zum Ende der Liste und fügen Sie das Symbol hinzu malloc_error_break
Frank Krueger
quelle
1
Ich habe das versucht, aber ich bekomme: nicht in der Lage, malloc_error_break zu entschlüsseln .... was bedeutet das?
Gonso
3
Keine Hilfe für Autorelease doppelt kostenlos. Er braucht Zombies
Rog
58
@gonso - Nur neugierig, wenn das bei dir nicht funktioniert hat, warum hast du es als Antwort akzeptiert?
Quinn Taylor
8
In Xcode 4.3.2 finden Sie die Haltepunkte in Ansicht → Navigatoren → Haltepunktnavigator anzeigen oder ⌘6 (Cmd-6)
Andreas Ley
46

Wenn ein Objekt "doppelt freigegeben" wird, ist die häufigste Ursache, dass Sie (unnötigerweise) ein automatisch freigegebenes Objekt freigeben. Es wird später automatisch freigegeben, wenn der enthaltende Autorelease-Pool geleert wird.

Ich habe festgestellt, dass der beste Weg, um die zusätzliche Version aufzuspüren, darin besteht, die Umgebungsvariable NSZombieEnabled für die betroffene ausführbare Datei in Xcode zu verwenden. Eine kurze Übersicht über die Verwendung finden Sie auf dieser CocoaDev-Wiki-Seite . (Zusätzlich zu dieser Seite hat Apple einige unglaublich undurchsichtige, aber nützliche Tipps zum Debuggen von Code in Xcode dokumentiert, von denen einige meinen Speck mehr als ein paar Mal gespeichert haben. Ich empfehle, diesen technischen Hinweis unter developer.apple.com - Link zu lesen springt zum Abschnitt über das Framework der Cocoa Foundation).

Bearbeiten: Sie können das fehlerhafte Objekt häufig im Xcode-Debugger aufspüren, aber es ist oft viel einfacher, wenn Sie Instrumente verwenden, um Sie zu unterstützen. Wählen Sie in Xcode Ausführen → Mit Leistungstool beginnen → Objektzuordnungen, und Sie sollten in der Lage sein, das fehlerhafte Objekt bis zu dem Ort zurückzuverfolgen, an dem es erstellt wurde. (Dies funktioniert am besten, wenn Sie Zombies wie oben beschrieben aktiviert haben.) Hinweis: Snow Leopard fügt Instrumenten ein Zombies-Tool hinzu, auf das Sie auch über das Menü "Ausführen" zugreifen können. Könnte allein die 29 Dollar wert sein! ;-);

Es gibt hier auch eine verwandte SO-Frage .

Quinn Taylor
quelle
1
CocoaDev Wiki-Seite in Antwort verlinkt ist tot :(
Devarshi
Verwenden Sie die Way Back-Maschine: web.archive.org/web/20120325135712/http://www.cocoadev.com/…
Quinn Taylor
13

Ich möchte nur meine Erfahrung zusätzlich zur Antwort von Quinn Taylor hinzufügen.

In einer meiner Apps muss ich Daten analysieren und in Kerndatenobjekten speichern und diese Objekte später in den Ansichten anzeigen lassen. Tatsächlich funktioniert die App einwandfrei und stürzt überhaupt nicht ab, bis ich mehrmals versucht habe, einen Stresstest zum Hin- und Herbewegen durchzuführen und mehrere Ansichten so schnell wie möglich zu öffnen. Die App stürzt mit der obigen Meldung ab.

Ich habe alle Methoden ausprobiert, die Quinn in seiner Antwort vorgeschlagen hat, und konnte immer noch nicht herausfinden, wo die genaue Ursache lag.

Ich habe NSZombieEnabled = YES und NSStackLogging = YES festgelegt und die Befehlsshell malloc_history ausgeführt, um herauszufinden, warum, aber immer noch kein Glück. Es wird immer darauf hingewiesen, wo ich die Daten in Kerndatenobjekten speichere. Tatsächlich habe ich die tausendfach freigegebenen Objekte dort tausendmal überprüft, nichts Seltsames.

Das Ausführen von Instrumenten mit verschiedenen Tools (Zuordnungen, Lecks usw.) hat immer noch nicht geholfen. Aktivieren Sie die Wache Malloc hat noch nichts.

Letzte Rettung: Ich habe versucht, zu den Ansichten zurückzukehren, in denen die Objekte aus Core Data entnommen wurden, und eine Aufbewahrungsnachricht an alle diese Objekte gesendet und diese Änderungen zur Kenntnis genommen. Es hat das Problem gelöst !!!

Also fand ich heraus, dass ich keinen behalten konnte, das ist genau die Ursache. Ich möchte nur meine Erfahrungen teilen, damit Sie eine weitere Rettung für Ihre App haben.

Hoang Pham
quelle
9

Öffnen Sie die Debugger-Konsole, indem Sie Cmd + Shift + R drücken. Geben Sie dort ein

break malloc_error_break

um einen Haltepunkt am Anfang der malloc_error_breakFunktion zu setzen.

Wenn Sie herausfinden möchten, welches Objekt sich unter der Adresse 0x1068310 befindet, können Sie Folgendes in die Debugger-Konsole eingeben:

print-object 0x1068310

Natürlich müssen Sie dies tun, während das Objekt noch lebt. Wenn das Objekt zu diesem Zeitpunkt bereits freigegeben wurde, funktioniert dies nicht.

Adam Rosenfield
quelle
Dies ist Autorelease, er braucht Zombies.
Rog
1
Schließlich habe ich die "verdächtige" Methode außerhalb von AutoreleasePoll aufgerufen. Komisch dachte ich habe immer noch die Warnung bekommen, aber es wurde kein Haltepunkt erreicht. Ich habe nur Blöcke auskommentiert, bis ich die Zeile gefunden habe. Ich habe eine Zeichenfolge, die mit stringWithFormat erstellt wurde, automatisch freigegeben (keine Zuordnung oder Kopie). Vielen Dank für Ihre Tipps! Gonso
Gonso
Für diese spezielle Art von Fehler hat das Brechen von malloc_error_break nie geholfen, das Problem zu finden - es war immer erforderlich, Zombies zu aktivieren.
Quinn Taylor
Anweisungen zum Festlegen eines Haltepunkts für malloc_error_break in XCode 4 finden Sie hier: stackoverflow.com/questions/6969407/…
benvolioT
1
@Zammbi: Versuchen Sie es mit dem poAlias ​​oder gleichwertig expr -o. In den Jahren, seit diese Antwort ursprünglich geschrieben wurde, wurde die von Xcode verwendete Debugging-Engine von GDB in LLDB geändert, und LLDB verfügt über einen anderen Befehlssatz.
Adam Rosenfield
4

Für mich wurde das Problem durch gelöst

(gdb) call (void)_CFAutoreleasePoolPrintPools()

gleich nach dem Absturz. Die Adresse oben im Stapel war die Adresse des Täters. retainWarf ein und voila.

Die in der Protokollnachricht angegebene Adresse brachte mich nicht weiter. Es tauchte in keinem der verschiedenen Instrumets auf. Anscheinend ein Zeiger auf einige interne Daten, die bereits freigegeben wurden.

c-alpha
quelle
4

Hinzufügen eines symbolischen Haltepunkts in Xcode 4

Nur ein Update, um dies für Xcode 4 relevant zu machen ...

Aus dem Xcode 4-Benutzerhandbuch :

Hinzufügen eines symbolischen Haltepunkts. . .

  1. Klicken Sie in der unteren linken Ecke des Haltepunktnavigators auf die Schaltfläche Hinzufügen.
  2. Wählen Sie Symbolischen Haltepunkt hinzufügen.
  3. Geben Sie den Symbolnamen in das Feld Symbol ein.
  4. Klicken Sie auf Fertig.
Alter McStopher
quelle
2

Überprüfen Sie Ihre Klassen und schauen Sie unter der Dealloc-Methode. Stellen Sie sicher, dass Sie anrufen möchten[super dealloc].

Ich hatte genau das gleiche Problem und fand heraus, dass ich [self dealloc]stattdessen anrief . Nur nicht aufpassen.

Wes Duff
quelle
2

In den folgenden Schritten erfahren Sie, wie Sie das freie Objekt finden und die Anwendung zum Absturz bringen.

1) Klicken Sie auf den " Breakpoint Navigator ".
2) Klicken Sie dann auf die Schaltfläche " + " unten.
3) Fügen Sie den " Symbolischen Haltepunkt ... " aus der Liste hinzu.
4) Fügen Sie das Schlüsselwort " malloc_error_break " in die Option " Symbol " ein.

Sie können auch auf die folgende GIF-Präsentation verweisen.

GIF-Repräsentation

Ramkrishna Sharma
quelle
1

Dies wird normalerweise von einigen Inspektoren verursacht, z. B. Safari oder Safari-Vorschau. Siehe Beitrag oder Beitrag und Frage .

Entfernen Sie die Auswahl von AutoMatisch Show Web ...., um dieses Problem zu beheben.

Beachten Sie, dass durch einfaches Schließen der Safari oder der Safari-Vorschau dieses Problem nicht behoben wird. Und Sie müssen sowohl die Safari- als auch die Safari-Vorschau deaktivieren.

Wenn dies nicht funktioniert, lesen Sie diese Antwort oder diesen Beitrag , um sie zu debuggen.

Deaktivieren Sie die automatische Überprüfung in der Safari-Vorschau

Kris Roofe
quelle
0

Klicken Sie in Xcode links neben der Zeilennummer, um einen Haltepunkt festzulegen. Dann können Sie es starten, indem Sie ein "Build and Debug" durchführen.

Es wird empfohlen, kein Objekt zu erstellen, das Sie erstellen, autoreleaseda Speicher auf dem iPhone eine Ware ist. Apple empfiehlt, ausdrücklich anzurufen release.

Benny Wong
quelle
0

Um diese Art von Speicher- und Zeigerproblemen im Allgemeinen zu finden, möchten Sie Ihren Code gegen eine Laufzeit-Speicherfehlerprüfung wie Valgrind ausführen . Dies sollte in der Lage sein, auf viele Dinge hinzuweisen, die Ihr Code falsch macht, über die hinaus, die zum Absturz führen.

Valgrind kann unter OSX arbeiten (obwohl es heißt, es sei "nicht unterstützt und unvollständig und fehlerhaft"), und mit ein wenig Hacking hat es jemand dazu gebracht, an ausführbaren iPhone SDK-Dateien zu arbeiten .

Noch besser können Sie Instruments ausprobieren, das Teil von XCode ist. Es gibt ein Tutorial es für die Ausführung von hier .

Jared Oberhaus
quelle
1
Instrumente ist der richtige Weg; Verwenden Sie das Objektzuweisungsinstrument und schalten Sie Zombies ein. (oder verwenden Sie einfach die Zombies-Vorlage). Valgrind ist die Lösung des letzten Auswegs. Es ist furchtbar langsam und funktioniert oft einfach nicht.
bbum
0

Wenn malloc_error_breaknicht hilft ...

Der beste Weg, um diesen Fehler zu beheben, besteht darin, Instrumente mit NSZombieseingeschaltetem Gerät zu betreiben . Instrumente kennzeichnen Sie, wenn der Zombie eine Nachricht erhält, und Sie können direkt zur Codezeile zurückverfolgen.

Schneeleopard erforderlich, was für ein Lebensretter!

iOSDevSF
quelle