Domanda

In ogni mio debugger è rotto o c'è qualcosa di fondamentale che non sto capendo.

Ho qualche codice molto di base in un programma a riga di comando molto semplice che incidente dovrebbe. Tuttavia, non si blocca.

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

    [string release];

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

    return 0;
}

Il "Lunghezza: 5" stampe log dichiarazione come ci si aspetterebbe per una stringa valida. Tuttavia, la stringa dovrebbe essere deallocato da quel punto e un errore exec_bad_access dovrebbe essere gettato.

Ho provato questo codice con il debugger e senza il debugger attaccato - sia dare lo stesso risultato. Ho anche attivato (e disabili) NSZombie, che sembra non avere alcun effetto (inizialmente ho pensato che questo era il problema, dato che gli oggetti non sono mai NSZombie deallocate - ma ancora non va in crash con NSZombie disabilitato).

Non ho punti di interruzione impostati nel mio file .gdbinit locali di rompere su cose come -[NSException raise] e objc_exception_throw. Ho anche i punti di interruzione impostati su molti metodi su NSZombie al fine di catturarli.

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

Con questi punti di interruzione impostati e NSZombie abilitati, dovrei ottenere qualcosa di simile [NSString length]: message sent to deallocated instance 0x100010d39 stampata alla console, ma non vedo questo. Vedo la NSLog stampa la lunghezza come 5.

vedo un comportamento simile con altre classi come NSURL e NSNumber. Ma alcune classi in crash come previsto, come ad esempio NSError e NSObject.

Questo ha qualcosa a che fare con i cluster di classe? Non hanno seguono le stesse regole per quanto riguarda la gestione della memoria?

Se i cluster di classe non sono legati a questo problema, l'unica altra caratteristica comune ho potuto vedere è che le classi che non crash in questo modo sono tutte colmato con una controparte Nucleo Fondazione numero verde. Questo potrebbe avere qualcosa a che fare con esso?

È stato utile?

Soluzione

retain / release è un contratto tra l'API e il programmatore che, quando si segue la regola, non in crash. Il contratto non garantisce che se non segue la regola, lo fa incidente!

In questo caso,

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

solo restituisce lo stesso oggetto come @"Hello" come un'ottimizzazione. Il NSString costante non è mai deallocata; come ottimizzazione, retain e release sono (credo) ignorato. Ecco perché non va in crash.

È possibile controllare la mia ipotesi confrontando il valore del puntatore di @"Hello" e string.

Altri suggerimenti

Questo è un ottimo esempio del perché conservano conta sono uno strumento di debug abbastanza inutile. E 'un errore ritenere -retain e -release sempre aggiungere o rimuovere dal 1 conservano contare e che la conservano conteggio è ciò che si pensa che dovrebbe essere.

Prova

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

Questo dovrebbe darvi una stringa che si comporterà più come il modo in cui vi aspettate dal momento che non si è inizializzazione la stringa da una costante di tempo di compilazione. Tuttavia, essere avvertito, con zombie abilitati, si otterrà il comportamento che ci si aspetta, ma senza zombie, il NSLog può ben funzionare. Anche se la stringa è stata deallocato, i dati in oggetto è ancora lì nella memoria lasciando un "fantasma" che risponderà correttamente a alcuni messaggi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top