2010-10-28 8 views
2

J'ai une trace de pile montrant un accident répondant à un avertissement de mémoire:CoreData: caches de purge crash après un avertissement mémoire

 
Thu Oct 28 00:42:55 iPhone DTMobileIS[10853] : _memoryNotification : {name = (null), num = 1} 


Thu Oct 28 00:42:55 iPhone DTMobileIS[10853] : _memoryNotification : { 
     OSMemoryNotificationLevel = 1; 
     timestamp = "2010-10-28 07:42:55 GMT"; 
    } 


Thu Oct 28 00:42:55 iPhone MyApp[11059] : Received memory warning. Level=1 

Thu Oct 28 00:42:55 iPhone MyApp[11059] : -[__NSCFType tryLock]: unrecognized selector sent to instance 0x41bfd0 

Thu Oct 28 00:42:55 iPhone MyApp[11059] : *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType tryLock]: unrecognized selector sent to instance 0x41bfd0' 

*** Call stack at first throw: 
(
    0 CoreFoundation      0x30897ed3 __exceptionPreprocess + 114 
    1 libobjc.A.dylib      0x3002f811 objc_exception_throw + 24 
    2 CoreFoundation      0x30899683 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102 
    3 CoreFoundation      0x308411d9 ___forwarding___ + 508 
    4 CoreFoundation      0x30840f90 _CF_forwarding_prep_0 + 48 
    5 CoreData       0x316cc261 -[_NSSQLCoreConnectionObsever _purgeCaches:] + 124 
    6 Foundation       0x349bb6b3 _nsnote_callback + 142 
    7 CoreFoundation      0x3081e713 __CFXNotificationPost_old + 402 
    8 CoreFoundation      0x3081e3b3 _CFXNotificationPostNotification + 118 
    9 Foundation       0x349aadb7 -[NSNotificationCenter postNotificationName:object:userInfo:] + 70 
    10 Foundation       0x349b42d1 -[NSNotificationCenter postNotificationName:object:] + 24 
    11 UIKit        0x31ed9431 -[UIApplication _performMemoryWarning] + 48 
    12 UIKit        0x31ec7383 -[UIApplication _receivedMemoryNotification] + 126 
    13 UIKit        0x31ec72c7 _memoryStatusChanged + 42 
    14 CoreFoundation      0x3084e825 __CFNotificationCenterDarwinCallBack + 24 
    15 CoreFoundation      0x30835313 __CFMachPortPerform + 210 
    16 CoreFoundation      0x3082cce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26 
    17 CoreFoundation      0x3082cca7 __CFRunLoopDoSource1 + 166 
    18 CoreFoundation      0x3081f56d __CFRunLoopRun + 520 
    19 CoreFoundation      0x3081f277 CFRunLoopRunSpecific + 230 
    20 CoreFoundation      0x3081f17f CFRunLoopRunInMode + 58 
    21 GraphicsServices     0x31e445f3 GSEventRunModal + 114 
    22 GraphicsServices     0x31e4469f GSEventRun + 62 
    23 UIKit        0x31e51123 -[UIApplication _run] + 402 
    24 UIKit        0x31e4f12f UIApplicationMain + 670 
    25 MyApp       0x00052c81 main + 72 
    26 MyApp       0x00002f18 start + 52 
) 

Je ne suis pas vraiment sûr de ce que les données de base a été fait qu'il a essayé de obtenir un verrou à partir de cet objet, mais j'ai l'impression que cela indique un problème de threading quelque part dans mon code.

Quelqu'un peut-il penser à un bon moyen de déboguer ce ou des causes profondes possibles?

Répondre

1

J'ai effectivement trouvé, après un peu d'analyse de code, la cause première de ce croisement de threads avec CoreData. J'ai eu un thread d'arrière-plan à partir d'une file d'attente d'opérations manipulant un NSManagedObjectContext qui est apparu sur le thread principal (et a causé un save! Ouch!). Après quelques-unes de ces manipulations, si j'ai envoyé un avertissement de mémoire dans le simulateur, l'application tomberait en panne.

+0

J'ai le même problème, quelle analyse de code avez-vous utilisée? Y a-t-il une astuce pour voir un mauvais accès au thread pour les objets de données de base? – steipete

+1

Xcode arrêtera votre application dans le simulateur ou sur le périphérique si vous exécutez une version de débogage. De là, j'ai pu voir l'histoire malloc de l'objet qui causait l'erreur, et voir qu'il s'agissait d'une instance de NSManagedObject. Après cela, j'ai ajouté une instruction log pour imprimer le contexte d'objet géré de chaque objet que j'ai manipulé, et cela m'a amené à voir qu'un objet appartenant à mon contexte de threads principal était manipulé sur un autre thread. – ImHuntingWabbits

+0

Merci d'avoir répondu à votre question, d'avoir le même problème ... Mais jamais reproduit dans un environnement de développement ... Maintenant, j'ai la cause! :) –

2

Je me suis heurté à cela récemment et trouvé une solution. Le bug est dans les données de base lui-même, et se manifeste dans les versions antérieures à iOS 5.1 (il semble être corrigé dans cette version).

Le blocage se produit lorsque le coordinateur de magasin persistant (PSC) ne parvient pas à charger un magasin persistant donné (par exemple parce que le schéma a changé). Dans ce cas, le magasin défaillant semble toujours être ajouté à un cache de données internes, même s'il n'y a pas d'accès externe. Ce cache est ensuite vidé automatiquement par les données de base lorsque l'application est en arrière-plan ou dans certaines situations de pression de mémoire. Tout va bien à moins que vous le PSC qui a été utilisé pour essayer de charger le magasin échoué a depuis été désalloué, auquel cas le cache essayera d'y accéder et donnera l'erreur ci-dessus.

Donc, pour résumer, vous frapperez cette erreur dans cette situation:

  • Essayez et ne parviennent pas à charger un magasin persistant à partir du disque. Cela se produira probablement parce que vous avez mis à jour votre application et que le schéma du modèle a changé.
  • Déplacez le coordinateur de magasin persistant que vous avez utilisé pour essayer de charger le magasin. Fond de l'application, ou dans certains cas, déclencher un avertissement de la mémoire.
  • crash

Pour contourner ce problème, il y a deux options. J'ai choisi de ne pas libérer le PSC en cas d'échec de l'appel à -addPersistentStoreWithType: configuration: URL: options: error: dans ce cas, la purge du cache accédera toujours à un PSC valide. Une alternative est de vérifier préventivement que le schéma du modèle correspond à la sur disque du système de stockage permanent en utilisant les deux appels suivants:

+[NSPersistentStore metadataForPersistentStoreWithURL:error:] 
-[NSManagedObjectModel isConfiguration:compatibleWithStoreMetadata:] 

La deuxième solution peut permettre d'éviter des fuites de la CFP dans certains cas rares, mais suppose également que la seule la façon dont un magasin persistant échouera à charger est due à des schémas de modèles incompatibles.

+0

Avez-vous déposé un radar pour cela? – ImHuntingWabbits

Questions connexes