Il bug più ricorrente nello sviluppo di applicazione per iPhone è EXC_BAD_ACCESS in un autorelease pool.
Vediamo cosa dobbiamo fare per scovarlo.
Gli strumenti necessari sono la classe NSZombie e l’applicazione malloc_history lanciata tramite terminale.
Supponiamo di avere il seguente pezzo di codice:
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSData* data = [NSData dataWithBytes:"asklaskdxjgr" length:12]; [data release]; [pool release];
Il metodo dataWithBytes manda un messaggio di autorelease all’oggetto, quindi non abbiamo bisogno del metodo release. Quando viene lanciato l’autorelease il sistema crasha, perchè l’oggetto non è più allocato.
Che cosa bisogna fare in questo caso?
In XCode 3.2 bisogna andare su Project ->Edit Active Executable “nome dell App” e nella sezione “Variables to be set in to environment ” aggiungere le seguenti variabili d’ambiente:
NSDebugEnabled NSZombieEnabled MallocStackLogging
Con NSZombieEnabled abilitato, Cocoa setta un puntatore ad un oggetto isa la classe NSZombie e solleva un’eccezione quando un’oggetto ha un retainCount uguale a 0, invece di deallocarlo.
2011-03-10 13:01:38.644 autoreleasebug[3939] *** *** Selector 'release' sent to dealloced instance 0xa4e10 of class NSConcreteData.
Sul terminale si può lanciare “malloc_history <pid> <address>” :
[soft@host193 Frameworks]$ malloc_history 3939 0xa4e10 Call [2] [arg=32]: thread_a0000dec |0x1000 | start | _start | main | +[NSData dataWithBytes:length:] | NSAllocateObject | object_getIndexedIvars | malloc_zone_calloc
Vuol dire che è stato fatto un doppio release sull’oggetto [NSData dataWithBytes:length:]
Compreso tutto? Buon lavoro.
Ultimi Commenti