Crash avec AutoSave
JegnuX
Membre
Heyy !
J'ai une Document Based Application, avec un custom NSDocument (=> PSDocument).
Si j'ai l'autosave activé ( +autosavesInPlace qui return YES), quand je ferme la fenêtre d'un document, mon application crashe (EXC_BAD_ACCESS).
Voici la pile d'appel au moment du crash :
$0 = 0x0000000106e513b0 <_NSCallStackArray 0x106e513b0>(
0 ??? 0x0000000102f6f13e 0x0 + 4344705342,
1 AppKit 0x00007fff8a8bf7c8 -[NSTableView _isGroupRow:] + 81,
2 AppKit 0x00007fff8a8baefd -[NSTableView _isSourceListGroupRow:] + 56,
3 AppKit 0x00007fff8a8ba838 -[NSTableView rectOfRow:] + 288,
4 AppKit 0x00007fff8a8d431b _NSTVVisibleRowsForUpdate + 296,
5 AppKit 0x00007fff8a8d39d5 -[NSTableRowData _unsafeUpdateVisibleRowEntries] + 96,
6 AppKit 0x00007fff8a8d37f1 -[NSTableRowData updateVisibleRowViews] + 119,
7 AppKit 0x00007fff8a8e73b3 -[NSTableRowData _idleUpdateVisibleRows] + 66,
8 CoreFoundation 0x00007fff86f42804 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20,
9 CoreFoundation 0x00007fff86f4231d __CFRunLoopDoTimer + 557,
10 CoreFoundation 0x00007fff86f27ad9 __CFRunLoopRun + 1529,
11 CoreFoundation 0x00007fff86f270e2 CFRunLoopRunSpecific + 290,
12 HIToolbox 0x00007fff87b9eeb4 RunCurrentEventLoopInMode + 209,
13 HIToolbox 0x00007fff87b9ec52 ReceiveNextEventCommon + 356,
14 HIToolbox 0x00007fff87b9eae3 BlockUntilNextEventMatchingListInMode + 62,
15 AppKit 0x00007fff8a751563 _DPSNextEvent + 685,
16 AppKit 0x00007fff8a750e22 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128,
17 AppKit 0x00007fff8a7481d3 -[NSApplication run] + 517,
18 AppKit 0x00007fff8a6ecc06 NSApplicationMain + 869,
19 MyApp 0x0000000100001742 main + 34,
20 libdyld.dylib 0x00007fff8fca07e1 start + 0
)
Pour info, au cas où, j'utilise ARC.
Merci d'avance
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Bonjour,
Ca ressemble à un zombie, non? Tu as une NSTableView dans le document que tu refermes?
J'ai un NSTableView mais aussi un NSOutlineView. J'ai pas pensé à activer les NSZombie. Je vais voir ce que ça donne.
Edit :
Alors j'ai activé les zombies du coup j'ai systématiquement un log :
Donc à un moment donné ça doit faire un reloadData ou un truc du genre, sauf que je vois vraiment pas où :-/
Bon... j'ai fait du method swizzling pour placer un log dans toutes les méthodes suivantes, mais aucune n'est appelée juste avant le crash.
Du coup je sais toujours pas qu'est ce qui est appelle mon windowViewController (le datasource/delegate), quand et pourquoi...
Vous voyez quoi d'autre comme méthode où je peux placer un log ?
J'ai eu un problème similaire, je m'en suis sorti en rajoutant au NSDocument un IBOutlet "mainWindow" sur sa fenêtre. Je crois qu'il y a une bulle quelque part, peut-être dans le template de Xcode. Toujours est-il que le décompte de ARC n'est pas correct. Essaie ça.
Les NSTableView appellent leur datasource dès que tu bouges l'affichage : il suffit parfois de déplacer la fenêtre pour que ça arrive. J'avais été "mordu" par ça à mes touts débuts mais à l'époque on utilisait les retain/release et c'était ça mon problème. Regarde si tu n'as pas une propriété weak plutôt que strong ça pourrait venir de ça ou plutôt à lire ton message d'erreur si tu as un pointeur solide sur ta outlineView. Mais comme je suis toujours en 32 bits je ne connais pas vraiment ARC et ne pourrais t'aider.
Merci pour votre aide. Mais le fait que ça ne crash que lorsque l'autosave est activé me parait bizarre quand même :-/
Le fait est qu'il faut que ça marche, AutoSave ou non. As-tu rajouté l'outlet sur la fenêtre? Voici mon post sur un autre site (désolé pour l'auto-citation):
Et la réponse du gourou du coin:
Si tu as la combinaison AutoSave + NSDocument/NSPersistantDocument + Core Data + ARC, les données sont réunies.
J'ai la combinaison AutoSave + NSDocument + ARC.
Le truc c'est que ça semble logique que la window soit release quand on la ferme.
De toute façon, même en rajoutant un outlet strong "mainWindow" de ma window vers mon windowViewController (le file's owner) j'ait toujours ce crash... :-/
Il y a une case à cocher "release when closed" regarde si elle n'est pas cochée dans le panneau Attributs de IB, ou utilise la méthode - (void)setReleasedWhenClosed:(BOOL)releaseWhenClosed.
Peut être cela changera t'il les choses mais c'est ton outlineView qui manque à l'appel alors je ne sais pas.
C'est pas plutôt un soucis du coté de ton document plus que ta fenêtre ?
Essaye de loguer ton NSDocument ou l'objet qu'il représente avant et regarde si c'est la même adresse qu'il essaye d'appeler.
En gros lorsque la fenêtre se ferme ça déclenche une sauvegarde certainement asynchrone pour ne pas bloquer l'UI, on dirait donc que quand le save s'exécute vraiment l'objet en charge du traitement du save n'est plus là .
À voir dans les cycles d'opération des NSDocument pour voir qu'est-ce qui doit être appeler quand et voir s'il n'y a pas des notes sur la gestion mémoire et ARC.
Avec Instruments on peut remonter jusqu'à l'objet fautif. Quand il s'arrête il met une bulle avec le signalement du zombie et, de mémoire, on peut cliquer sur une petite flèche et on peut alors avoir plus de détail sur l'objet, dont sa classe et on voit la liste des "retain" "release" de l'objet (ARC les fait pour nous mais on doit pouvoir les suivre dans Instruments). En double cliquant sur les élements de la liste on peut même voir l'endroit du code où ça se passe mais là avec ARC je suis pas certain ...
Un petit exemple avec le simple code suivant
Lancé via Instruments bloque bien sûr là où ça coince
Bon j'ai regardé mais ça ne m'aide pas. Au final je tombe sur la même callstack que depuis Xcode (normal).
J'essaie de suivre la piste de Yoann sur le NSDocument et je me disais que ça vient ptet du fait que j'ai pas encore implémenté le undo manager de mon NSDocument ? du coup mon changeCount ne bouge pas et ça fait foirer l'autosave ?
Mais bon ça me dit pas qui demande à mon outline view de se refresh...
Car si dans mon -windowWillClose: je met le delegate et le datasource à nil, j'ai plus aucun crash.
Mais bon, ça s'appelle masquer le problème au lieu de le résoudre à la source et j'aime pas ça...
Essaie d'isoler le bug au maximum dans un nouveau projet et de le submit à Apple si ça se reproduit bien. C'est fort probable que ce problème soit le leur.
Je vais essayer ouai.
Bien vu ! J'ai pu très simplement refaire un projet qui crash : http://cl.ly/0I3v2c340A2K
Je vous laisse regarder vite fait quand même pour voir si ça viendrait quand même pas d'un truc qui manque...
ça plante pas moi
alors j'avoue que ca plante pas a chaque fois sur ce sample. Essai par exemple de sauvegarder le fichier. Quitter. Ouvrir le fichier, et fermer la window.
Chez moi ça plante facilement, juste eu à enregistrer un document que je ré-ouvre via open recents et quand je le ferme (ou parfois la untitled window du document de départ) ça crash.
Le côté intéressant c'est que quand ça le fait, avec les NSZombies Enabled dans le Scheme du projet alors il me dit que c'est un CSDocument qui n'est plus là pour répondre au sélecteur.
Et si je le lance via Instruments il semble que le problème vienne de AppKit qui en a encore besoin alors qu'il vient d'être relâché, probablement une fois de trop par un [NSAutoreleasePool drain] lancé par Foundation à la sortie d'un _destroy_helper_block créé par Apple.
Je dois mal m'y prendre, j'ai beau essayer toutes vos manipulations plus quelques-unes de mon cru, l'application est d'une stabilité remarquable...
Ah... faux. ça plante hors-Xcode. Quand je lance l'app depuis un document et et je le ferme ensuite.
Xcode 4.6.2 (4H1003)
Bon, c'est peut être pas LA solution mais en tout cas pour moi ce matin c'est est une.
Déclarer une variable IBOutlet NSOutlineView *sourceList, ajouter @synthesize sourceList dans l'implémentation pour qu'elle soit utilisée plutôt que d'avoir une variable _sourceList créée automatiquement.
Plus de crash.
ça n'explique pas le problème mais ça le résout : avec ça l'appli refuse de se planter.
Quoique, si je supprime ma modification pour vérifier que c'est bien ça, ça ne crashe toujours plus !
Entre deux un événement pas ordinaire : ce matin le mac me montrait un dialogue pour me dire qu'il avait dû redémarrer pendant la nuit à cause d'une erreur. Mais je n'ai pas réussi à voir laquelle.
Donc je repartais sur un système tout "frais".
Ce qui explique peut être, aussi, pourquoi ça ne crashe plus ..
Ce serait donc bien lié à un mauvais décompte de ARC? J'ai peine à croire qu'un truc aussi simple et courant ait échappé aux ingénieurs d'Apple, pas vous ?
Sais pas, faut voir si c'est bien la solution puisque ça ne le fait plus même si je supprime cette variable et le @synthesize pour revenir au code du début. Il faudrait voir ce que ça donne pour jegnuX.
C'est peut être aussi dû au fait que ma machine a redémarré toute seule et que le système est plus "stable".
Par contre ce genre de bugs qui n'apparaà®t qu'à certaines conditions pourrait tout à fait avoir échappé à Apple je pense. Quand ça plantait il y avait plusieurs threads qui étaient lancés par AppKit et pas par le peu de code de CrashSample..
Ils restent humains quand même
... ouf, voilà qui me rassure. Pas de Deus ex machina. A propos d'humains, j'ai soumis un bug report à Apple concernant un problème de base localization sur les NSSegmentedControls... il y a neuf mois, il est resté ignoré. Est-ce un délai lié à leur humanité?
Oh j'ai report un bug lié à une API d'iOS y'a 2 ans alors bon.