2011-06-11 8 views
16

Je travaille sur un projet sur iPhone. Je lance maintenant un nouveau UIViewController à partir d'un autre UIViewController, puis basculer entre eux. Voici mon code.Objet a été probablement modifié après avoir été libéré

iGreenAppDelegate *delegate = [UIApplication sharedApplication].delegate; 
if(checkInViewController) { 
    [checkInViewController release]; 
    checkInViewController = nil; 
} 
checkInViewController = [[CheckInViewController alloc] initWithCheckpoint:checkpoint]; 

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDuration:0.8]; 
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:[delegate window] cache:YES]; 
[[delegate rootTabBarController].view removeFromSuperview]; 
[[delegate window] addSubview:checkInViewController.view]; 
[UIView commitAnimations]; 

Le problème est la deuxième fois que je lance le UIViewController, je veux le libérer pour éviter de provoquer la fuite de mémoire. Le Débogueur affiche

iGreen (916,0x3f60348c) malloc: erreur pour objet 0x130350: contrôle incorrect pour objet libéré - objet a probablement été modifié après avoir été libéré. définir un point d'arrêt dans malloc_error_break pour déboguer

Ceci est étrange parce que des codes similaires dans d'autres parties ne reviennent pas une telle erreur. De plus, j'ai essayé autorelease, mais le programme va se bloquer immédiatement et le débogueur dit que je suis en train de modifier les calques finalisés.

J'ai travaillé sur le problème pendant une nuit entière, et encore confus à ce sujet.

+0

Par ailleurs, si je ne libère pas le viewcontroller, le programme fonctionne très bien, mais je ne pense pas que ce soit une bonne façon de le résoudre. Quelqu'un peut-il m'aider à trouver le problème? – Stone

+0

Difficile de suivre ce qui se passe dans votre code à partir de cet extrait, mais généralement vous avez juste besoin d'allouer le contrôleur de vue, ajoutez-le à votre contrôleur de tabulation, puis relâchez le contrôleur. Le contrôleur de barre d'onglets conserve le viewcontroller pour qu'il reste en place. Il me semble que vous le libérez avant que le contrôleur de tabulation ne soit terminé. Peut-être que vous pouvez ajouter plus de code à cette question pour plus de clarté? –

+0

pouvez-vous ajouter votre implémentation initWithCheckpoint? Aussi, avez-vous essayé de construire et d'analyser dans le menu Xcode? – AmineG

Répondre

18

Définissez un point d'arrêt dans malloc_error_break à déboguer.

Faites-le et postez le backtrace.

Habituellement, cela signifie que vous avez corrompu la mémoire, mais cela peut aussi signifier que vous avez un objet trop relâché. Essayez de construire et d'analyser, aussi.

+8

Et comment puis-je faire cela? Comment définir un point d'arrêt dans malloc_error_break? –

+34

@ JCLeitão Run> Breakpoints> Ajouter un point d'arrêt symbolique> puis mettre "malloc_error_break" – geekazoid

+2

@geekazoid, Merci, je pense que cela va aider les autres aussi ... :) –

3

Comprendre le message d'erreur: il est dit que quelque chose a continué à utiliser (et à modifier) ​​l'objet après l'avoir libéré. Ce code le libère et ne le modifie pas par la suite, mais vous devez demander à quoi d'autre pourrait continuer à l'utiliser (sans savoir qu'il était déjà libéré).

Chaque fois que le code de cet extrait s'exécute, il libère (libère) un checkinViewController existant et en alloue un nouveau, et il ne touche plus à l'ancien. Mais qui d'autre peut avoir un pointeur vers le vieil objet?

Peut-être un autre code que vous avez écrit, et éventuellement [fenêtre de délégation], qui obtient une référence via "[[delegate window] addSubview: checkInViewController.view];"? Espérons que ce dernier prenne sa propre référence, ce qui signifie que la publication ne le libérera pas immédiatement.

Mais attention à l'endroit où vous copiez ce pointeur sans ajouter de référence. Si vous le faites quelque part, puis ailleurs (comme l'extrait ci-dessus) quelqu'un appelle la publication sur le même pointeur, vous pouvez maintenant avoir un pointeur vers un objet qui a été libéré.

1

Il y a quelques erreurs dans la conception de votre code. Commencez par supprimer checkInViewController sans supprimer sa vue de sa vue d'ensemble (le cas échéant), puis supprimez la vue rootTabBarController de sa vue d'ensemble, sans rien faire au contrôleur lui-même, et vous n'ajoutez pas checkInViewController à rootTabBarController ou à la propriété rootViewController de la fenêtre, donc c'est dans l'air (juste retenu par votre objet actuel). Que se passe-t-il lorsque cet objet (actuel) est désalloué mais que la vue de checkInViewController reste positionnée (conservée par) sur la fenêtre?

Si vous relâchez votre checkInViewController mais son point de vue est Maintenu par la fenêtre, il va probablement créer des problèmes ...

A propos de l'erreur, je pense qu'il ya quelque part une référence faible (non retenu) à votre objet qui agit après sa libération.

9

Outre la définition d'un point d'arrêt dans malloc_error_break - appuyez sur Commande-6 dans xCode pour passer à l'onglet des points d'arrêt - activez également les aides malloc dans votre schéma. Aller dans le sélecteur de schémas, choisir "Schéma d'édition" trouver la cible "Exécuter" et aller à l'onglet "Diagnostic". En dessous de la gestion de la mémoire, activez les griffonnages, les bords de garde, les objets de garde malloc et zombie. Avec un peu de chance, xCode vous surprendra à écrire en dehors de la mémoire allouée et à corrompre la mémoire.

Il est comme la surveillance des adultes pour faire face à la mémoire ...

+0

Tue la performance, espère encore la peine. Essayer ... :) – Narek

+0

Killing performances, tout en débogage, afin de trouver un bug me semble OK. –

Questions connexes