2010-04-17 8 views
3

Ceci est un (très) version simplifiée de mon code iPhone:je reçois un "EXC_BAD_ACCESS" lorsque je tente de lire un NSString

@interface x {
NSString * nom1;
NSString * nom2;
}

-init {
nom1 = @ "";
nom2 = @ "";
}

- (void) {un
Foo * foo = [Foo alloc];
nom1 = @ "uhuh";
nom2 = [barre toto]; // Renvoie un (NSString *)
[foo release];
}

- (void) b {
NSLog (@ "% @", nom1); // cela fonctionne
NSLog (@ "% @", name2); // là j'obtenir un EXC_BAD_ACCESS ...
}

Pourquoi j'avoir ce problème? Et comment puis-je le résoudre?
Merci!

Edit: Je Justė résoudre le Problème, j'ai oublié un "retain" ...

Répondre

0

Je recevais une erreur de EXC_BAD_ACCESS hier. Il s'est avéré que j'appelais release sur un objet qui a entraîné sa suppression, puis j'ai essayé de l'utiliser.

Vous n'appelez pas release sur quoi que ce soit que vous n'êtes pas supposé être? Un simple rappel: si vous n'appelez pas alloc ou retain sur un objet, vous n'appelez pas release. Avec le code que vous avez fourni, il ne semble pas que ce soit le problème. Mais je voulais le signaler au cas où.

0

Joel a raison. essayez de regarder votre fonction [barre de foo], peut être dans cette fonction que vous libérez un objet

1

Vous devez lire le Cocoa Memory Management Guide. Certaines des choses que vous faites dans le code montrent que vous ne maîtrisez pas les concepts fondamentaux de la gestion de la mémoire cacao.

Par exemple:

[Foo alloc]; 

Vous n'êtes pas initialisant 'foo'. Il est de pratique courante de coupler alloc et init appels ensemble, par exemple: [[Foo alloc] init]; Cela garantira que les objets membres et l'état est ce que vous attendez après la création.

name2 = [foo bar]; // returns a (NSString *) 

Le procédé bar est susceptible de renvoyer une chaîne autoreleased.Vous ne le retenez pas après l'avoir affecté à name2, il sera donc désalloué quelque temps après le retour de la méthode. Et c'est pourquoi votre code plante. Vous essayez d'accéder à un objet désalloué. L'objet pointé par name2 a été libéré et désalloué, mais le pointeur n'a pas été défini sur zéro, ce qui signifie que la mémoire vers laquelle il pointe peut maintenant contenir n'importe quoi. C'est indéfini.

La raison pour laquelle fonctionne name1 est due à une attention particulière à l'utilisation des chaînes littérales @ "" dans Cocoa. Quand une chaîne est utilisée comme ça, elle devient "intériorisée". Si vous créez deux chaînes littérales contenant le même texte, le système l'optimisera afin que ces deux chaînes pointent vers un objet en mémoire.

C'est-à-dire que si vous avez du code qui ressemble à ceci:

NSString *myString1 = @"hello"; 
NSString *myString2 = @"hello"; 

NSLog(@"string1: %p, string2: %p", myString1, myString2); 

il en résulterait un message ressemblant à: string1: 0x123456, string2: 0x123456. La chose importante à noter ici est que les adresses de mémoire sont les mêmes. Les chaînes pointent sur le même objet, même s'il s'agit d'instances différentes dans le code.