Warum könnte ein veröffentlichtes Objekt in - [_ PFManagedObjectReferenceQueue _queueForDealloc:] abstürzen?

8

Ich sehe gelegentlich Abstürze mit einem Stack-Trace wie folgt:

%Vor%

Leider ist es ziemlich zufällig zu reproduzieren. Hat jemand Ideen, was einen solchen Absturz verursachen könnte? Es hilft nicht, dass niemand -_queueForDealloc: schon einmal im Internet erwähnt hat!

Ich habe eine vage Erinnerung an ein ähnliches Problem in der Vergangenheit, bei dem dies ein Symptom für die Freigabe eines verwalteten Objekts war, während noch KVO-Beobachter angeschlossen waren. Jeder stimmt zu?

    
Mike Abdullah 08.03.2011, 14:58
quelle

4 Antworten

11

Nachdem das Problem endlich auf einer Entwicklungsmaschine reproduziert werden konnte, scheint dieser Absturz ein Nebeneffekt einer früheren Ausnahme beim Kontext-Teardown zu sein.

Die Reihenfolge der Ereignisse ist ungefähr wie folgt:

  1. Die MOC wird freigegeben, daher ist es an der Zeit, den Inhalt zu löschen
  2. Dazu werden alle registrierten MOs in Fehler *
  3. umgewandelt
  4. Der Vorgang, bei dem ein MO in einen Fehler umgewandelt wird, sendet KVO-Benachrichtigungen
  5. Ein Beobachter erhält die Benachrichtigung und versucht, darauf zu reagieren, indem er in der Grafik
  6. eine jetzt ungültige MO trifft
  7. Core Data löst eine Ausnahme vom ungültigen Zugriff aus
  8. aus
  9. Aus unbekannten Gründen wird diese Ausnahme nicht an meinen Ausnahme-Reporter
  10. übergeben
  11. Die MO s werden freigegeben, aber die Ausnahme hat Core Data in einem unerwarteten Zustand hinterlassen, so dass die MO Freigabe fehlschlägt

Kurz gesagt besteht das eigentliche Problem darin, dass Beobachter den Kontext überleben; erlaube ihnen nicht! Jedes Objekt, das MO beobachtet, sollte wahrscheinlich auch eine starke Referenz auf MOC haben, wie NSObjectController und Freunde tun.

* Ich habe beim Testen festgestellt, dass Core-Daten dies oft in einem Hintergrundthread tun, vermutlich um den Hauptthread nicht zu blockieren

MOC - Kontext des verwalteten Objekts
MO - verwaltetes Objekt

    
Mike Abdullah 10.03.2011, 13:39
quelle
2

-_queueForDealloc: ist eine nicht dokumentierte interne Methode. Es zeigt sich von Zeit zu Zeit in Stapeln, aber es ist nichts, womit wir direkt umgehen.

Ihr Problem wird höchstwahrscheinlich durch die Überlassung eines managedObject verursacht. Ein managedObject wird stark von einem Kontext beibehalten, der das Objekt einfügt, aktualisiert oder ändert. Wenn Sie also die objekteigene Aufbewahrung mikromantieren, können Sie sie vor der Freigabe des Kontexts überladen. Dies führt dazu, dass das verwaltete Objekt scheinbar zufällig verschwindet. Umgekehrt können Sie ein Objekt beibehalten, das nach dem Löschen durch den Kontext bestehen bleibt.

Ich ermutige Menschen, verwaltete Objekte nicht zu behalten, aber wenn Sie dies tun, legen Sie ihnen eine Klasseneigenschaft oder eine Sammlung wie ein Array oder einen Satz. Auf diese Weise wird die Aufbewahrung für Sie erledigt.

    
TechZen 08.03.2011 22:24
quelle
1

Wir sind auf ein ähnliches Problem gestoßen, als wir einen privaten Kontext für verwaltete Objekte innerhalb von NSOperation verwendet haben. Wir haben damit umgegangen, indem wir alle Parameter abgeschwächt und eine private @autoreleasepool verwendet haben. Ich werde weiter unten näher ausführen.

Unsere aktuelle Konfiguration hat eine NSOperationQueue , die eine lang laufende Berechnung hat, die wir im Hintergrund machen. Die Operation erstellt zuerst einen privaten verwalteten Objektkontext mit dem übergeordneten Set als Hauptobjektkontext und geht und ruft ihre Objekte ab.

In der Zwischenzeit haben wir ein separates NSOperationQueue an anderer Stelle, das neue Daten von unserem Server synchronisiert und möglicherweise Objekte hinzufügt, aktualisiert oder entfernt, die von unserer Rechenoperation verwendet werden.

Wir sahen zuerst eine Menge dieser Abstürze in der Wildnis und die einzige Möglichkeit, sie lokal zu reproduzieren, besteht darin, dass sowohl Rechen- als auch Synchronisierungsoperationen kontinuierlich ausgeführt werden und nach 5 bis 10 Minuten ein Absturz ähnlich einem der beiden erscheinen würde unten:

%Vor%

Wir haben den Code mehrfach überprüft und konnten nicht feststellen, warum er abgestürzt ist. Wir haben versucht, NSZombies zu aktivieren, aber wir hatten keinen Speicher mehr, lange bevor wir eine Repro erhalten konnten.

Was wir am Ende gemacht haben, sind die folgenden 2 Dinge:

@autoreleasepool

In unserem [privateObjectContext performBlockAndWait:^{…}] , das sich in unserem NSOperationBlock befindet, haben wir den gesamten Code in ein @autoreleasepool{…} gehüllt. Auf diese Weise werden alle NSManagedObjects, die während dieses Codeblocks abgerufen wurden, zur Freigabe markiert, bevor sie performBlockAndWait verlassen.

schwächen / verstärken

Alle Parameter, die NSManagedObjects enthalten, wurden vor dem Übergeben in den Block abgeschwächt und im Block einmal verstärkt. Auf diese Weise können wir sie loslassen, wenn sie veraltet sind, während wir auf den Start von NSOperation warten. Hier ist ein guter Artikel über die Funktionsweise von weakify / strongify: Ссылка

    
Toland Hon 18.02.2015 23:26
quelle
0

Ich habe eine andere Lösung, um diesen Fehler zu beheben. In Beispielen sehen MOC-Eigenschaften für ARC wie (nur gelesen, stark, nichtatomisch) aus

Nach Wochen des Tanzens über diesen Zeit-zu-Zeit-Absturz habe ich eine Lösung für osx (entferne einfach nicht-atomare).

Jetzt ist es perfekt, alle Abstürze gehen aus.

    
user170317 04.07.2013 08:00
quelle