Question

Soit mon débogueur est cassé ou il y a quelque chose de fondamental que je ne comprends pas.

J'ai un code très basique dans un programme de ligne de commande très simple que devrait accident. Cependant, il ne s'écraser.

int main (int argc, const char * argv[])
{
    NSString *string = [[NSString alloc] initWithString:@"Hello"];

    [string release];

    NSLog(@"Length: %d", [string length]);

    return 0;
}

La déclaration journal affiche « Longueur: 5 » que vous attendez d'une chaîne valide. Cependant, la chaîne doit être libérée par ce point et une erreur de exec_bad_access doit être levée.

J'ai essayé ce code avec le débogueur ci-joint et sans le débogueur attaché - les deux donnent le même résultat. J'ai également activé (et désactivé) NSZombie, qui semble avoir aucun effet (je pensais d'abord c'était le problème, car les objets ne sont jamais NSZombie désallouées - mais il ne fonctionne toujours pas avec NSZombie crash désactivé).

J'ai points d'arrêt dans mon fichier .gdbinit local pour briser des choses telles que -[NSException raise] et objc_exception_throw. J'ai aussi mis sur plusieurs points d'arrêt sur les méthodes NSZombie afin de les attraper.

fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]

#define NSZombies
# this will give you help messages.  Set to NO to turn them off.
set env MallocHelp=YES
# might also be set in launch arguments.
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1

set env CFZombie 5

fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]

fb szone_error
fb objc_exception_throw

Avec ces points d'arrêt et NSZombie ont permis, je devrais obtenir quelque chose comme [NSString length]: message sent to deallocated instance 0x100010d39 imprimé à la console, mais je ne vois pas cela. Je vois l'impression NSLog la longueur 5.

Je vois le même comportement avec d'autres classes telles que NSURL et NSNumber. Mais certaines classes s'écrasent comme prévu, comme NSError et NSObject.

Est-ce que cela a quelque chose à voir avec les clusters de classe? Suivent-ils pas les mêmes règles en ce qui concerne la gestion de la mémoire?

Si les clusters de classe ne sont pas liés à ce problème, la seule autre caractéristique commune que je pouvais voir était que les classes qui ne plantent pas de cette façon sont pontées avec une contrepartie Core Foundation sans frais. Pourrait-il avoir quelque chose à faire?

Était-ce utile?

La solution

retain / release est un contrat entre l'API et le programmeur que lorsque vous suivez la règle, il ne tombe pas en panne. Le contrat ne garantit pas que si vous ne suivez pas la règle, il ne accident!

Dans ce cas,

[[NSString alloc] initWithString:@"Hello"]

retourne juste le même objet que @"Hello" comme une optimisation. La NSString constante est jamais désallouée; comme une optimisation, retain et release sont (je pense) ignoré. Voilà pourquoi il ne tombe pas en panne.

Vous pouvez vérifier mon estimation en comparant la valeur de pointeur de @"Hello" et string.

Autres conseils

Ceci est un excellent exemple des raisons pour lesquelles conservent compte sont un outil de débogage assez inutile. Il est erroné de supposer -retain et -RELEASE toujours ajouter ou supprimer 1 du compte et que conserver Retain compte est ce que vous pensez qu'il devrait être.

Essayez

NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];

Cela devrait vous donner une chaîne qui se comportera comme la façon dont vous attendez puisque vous n'êtes pas INITIALISATION votre chaîne à partir d'une constante de compilation. Cependant, attention, avec des zombies activés, vous obtiendrez le comportement que vous attendez mais sans zombies, le NSLog peut bien fonctionner. Bien que la chaîne a été désallouée, les données de l'objet est là encore en mémoire laissant un « fantôme » qui répondra correctement à certains messages.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top