2011-01-13 2 views
0

j'ai déterminé que mon application se bloque sur la ligne suivante:L'impression d'une NSMutableArray provoque une panne sans code d'erreur

if(sourceValues != nil && [sourceValues class] == [NSMutableArray class]) 
    [sourceValues release]; 

« sourceValues ​​» est déclarée comme NSMutableArray au sommet de ma classe. La boucle "if" est satisfaite et l'appel [sourceValues ​​release] est effectué, ce qui bloque le programme sans code d'erreur. Donc, depuis sourceValues! = Nil et depuis [classe sourceValues] == [classe NSMutableArray], je voulais voir exactement ce que sourceValues ​​était. Ainsi, au-dessus du « si » boucle j'ajouté ce qui suit:

NSLog(@"sourceValues is %@", sourceValues); 

Mais mon programme ne sera pas l'imprimer. Il se bloque juste sans code d'erreur sur cette ligne. Donc, si sourceValue existe et si c'est un NSMutableArray, pourquoi ne sera-t-il pas imprimé. Quel est le problème ici?

J'essaye d'avoir du code qui dit "si des sourcesValues ​​ont été allouées, libérez-le." Comment puis-je faire ceci?

+0

De même, comment 'sourceValues' est-il alloué? – joshpaul

Répondre

1

Pourquoi ne pas utiliser:

if(sourceValues != nil && [sourceValues isKindOfClass:[NSMutableArray class]]) 
    [sourceValues release]; 

Vous pouvez utiliser d'autres méthodes comme:

  • isMemberOfClass:
+0

le problème existe toujours, mais merci pour le conseil. – CodeGuy

+0

Si le problème persiste, cela signifie que le problème est lié à la libération de votre objet. Vous pouvez nous montrer le reste du code. –

+1

Aucune vérification de 'sourceValues' ne sera utile si' sourceValues' est déjà disponible. – bbum

-1

Essayez de vérifier retainCount, quelque chose comme:

NSLog (@ "retain count:% d", [sourceValues ​​retainCount]);

Utiliser UNIQUEMENT pour tester/déboguer, ne comptez pas sur ceci dans une instruction if.

De même, vous pouvez essayer d'effectuer une itération sur des valeurs source et d'imprimer son contenu dans NSLog, mais je n'ai aucune idée de ce qui s'y trouve.

La meilleure chose à faire est de configurer une propriété de classe en tant que MSMutableArray avec RETAIN, et d'utiliser synthesize. Le dealloc prendra soin de la libération.

Si ce qui précède est mis en œuvre, vous pouvez alloc/init comme suit:

self.sourceValues = [[[NSMutableArray alloc] init] autorelease]; 

puis ajouter des objets directement à self.sourceValues ​​au besoin. Pas besoin de s'inquiéter de la libération, ça se fera en dealloc.

+0

autoreleasing ne fonctionnera pas pour la configuration que j'utilise. Je n'utilise pas dealloc pour effacer les choses. – CodeGuy

+0

pourquoi ne pas utiliser dealloc? Ne compliquez pas les choses pour vous-même;) – tbone

+1

'-retainCount' ne devrait pas être utilisé. Pas même pour le débogage. – bbum

0

Eh bien, tout d'abord, il n'y a aucun danger à libérer un objet nil. Donc, le problème de "si sourceValues ​​a été alloué, libérez-le." est probablement superflu. Vous devez suivre les règles de gestion de la mémoire habituelles et appeler simplement [sourceValues release]; dans dealloc

Avez-vous essayé d'exécuter tout avec des points d'arrêt ("Build and Debug - Breakpoints On" dans Xcode)? Cela vous donne généralement plus d'informations de débogage que les habituelles "Build and run".

Il se peut que vous ayez déjà désalloué sourceValues, mais le pointeur pointe toujours vers son ancienne mémoire (je suppose en fonction de problèmes étranges que j'ai rencontrés dans le passé). Si cela se produit, un nouvel objet pourrait être situé dans cette zone que le programme tentera quand même de traiter comme un NSMutableArray.

+0

mais je n'utilise pas dealloc. est-ce qu'il n'y a pas un moyen de dire simplement "si X a été alloué, relâchez-le" – CodeGuy

+1

Vous n'utilisez pas dealloc? On dirait que vous faites quelque chose de mal ... la libération ne libère jamais réellement de la mémoire; il est seulement responsable de l'abaissement du nombre de retenues de 1. Si le nombre de retenues atteint 0, dealloc est appelé pour libérer la mémoire. – vicvicvic

+1

Pourquoi ne pas simplement le libérer? Vous pouvez envoyer la version à zéro sans effets indésirables. – joshpaul

1

Si cela ...

NSLog(@"sourceValues is %@", sourceValues); 

... se bloque votre programme, il est parce que sourceValues a déjà été publié. Où que vous releasesourceValues, définissez-le sur nil.

[sourceValues release], sourceValues = nil; 

Si votre application plante toujours, c'est parce que la baie a été sur-libérée ailleurs. Autrement dit, vous n'avez pas correctement équilibré les retenues et les versions. Tout d'abord, essayez de "construire et analyser" et de résoudre tous les problèmes identifiés par l'analyseur statique. Ensuite, activez la détection de zombies et voyez d'où vous envoyez la première fois l'objet sur-relâché.

Notez que [sourceValues class] == [NSMutableArray class] ne fonctionnera pas et ce modèle ne doit jamais être utilisé pour vérifier si une instance est d'une classe particulière. Vous devriez toujours utiliser isKindOfClass: ou isMemberOfClass:.

Cependant, comme vous ne pouvez pas faire la différence entre un tableau mutable ou un tableau immuable, il n'y a aucun intérêt à vérifier en premier lieu.

Questions connexes