Domanda

Sono nuovo nello sviluppo di iPhone e XCode in generale e non ho idea di come iniziare a risolvere un segnale EXC_BAD_ACCESS . Come posso fare in modo che XCode si interrompa sulla riga esatta che causa l'errore?


Non riesco a far arrestare XCode sulla linea causando il problema, ma vedo le seguenti righe nella mia console di debug:

  

Dom 25 ott 15:12:14 jasonsmacbook   TestProject [1289]:   CGContextSetStrokeColorWithColor:   contesto non valido

     

Dom 25 ott 15:12:14 jasonsmacbook   TestProject [1289]:   CGContextSetLineWidth: contesto non valido

     

Dom 25 ott 15:12:14 jasonsmacbook   TestProject [1289]:   CGContextAddPath: contesto non valido

     

Dom 25 ott 15:12:14 jasonsmacbook   TestProject [1289]:   CGContextDrawPath: contesto non valido

     

25/10/2009 15: 12: 14.680   LanderTest [1289: 207] *** - [CFArray   objectAtIndex:]: messaggio inviato a   istanza deallocata 0x3c4e610

Ora sto tentando di attingere al contesto recuperato da UIGraphicsGetCurrentContext () e passare all'oggetto con cui voglio disegnare.


Ulteriore prova di errori e debug e ho scoperto che un NSMutableArray di cui ho una proprietà per la mia classe era uno zombi. Sono entrato nella funzione init per la classe ed ecco il codice che stavo usando:

if ((self = [super init])) {
        NSMutableArray *array = [NSMutableArray array];
        self.terrainBlocks = array;
        [array release];
    }
    return self;    
}

Ho rimosso la riga [array release] e non mi dà più il segnale EXC_BAD_ACCESS , ma ora sono confuso sul perché funzioni. Quando ho usato la proprietà, ho pensato che la conservasse automaticamente per me, quindi avrei dovuto rilasciarla da init in modo da non avere una perdita. Sono completamente confuso su come funziona e tutte le guide e le domande StackOverflow che ho letto mi confondono di più su come impostare le proprietà nel mio metodo init. Sembra che non ci sia consenso su quale sia il modo migliore.

È stato utile?

Soluzione

Per eventuali errori EXC_BAD_ACCESS, in genere si sta tentando di inviare un messaggio a un oggetto rilasciato. Il MIGLIORE per rintracciarli è utilizzare NSZombieEnabled .

Funziona non rilasciando mai realmente un oggetto, ma avvolgendolo come uno "zombi" e impostando una bandiera al suo interno che dice che normalmente sarebbe stato rilasciato. In questo modo, se provi ad accedervi di nuovo, sa ancora che cosa era prima di aver commesso l'errore e con questa piccola informazione, di solito puoi tornare indietro per vedere quale fosse il problema.

Aiuta soprattutto nei thread in background quando il Debugger a volte cerca informazioni utili.

MOLTO IMPORTANTE DA NOTARE , tuttavia, è che è necessario assicurarsi al 100% che questo sia solo nel codice di debug e non nel codice di distribuzione. Poiché non viene mai rilasciato nulla, l'app perderà, perderà e perderà. Per ricordarmi di farlo, ho inserito questo registro nel mio delegato dell'app:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");

Se hai bisogno di aiuto per trovare la riga esatta, esegui un Build-and-Debug ( CMD-Y ) invece di Build-and-Run ( CMD-R ). Quando l'app si arresta in modo anomalo, il debugger ti mostrerà esattamente quale linea e in combinazione con NSZombieEnabled, dovresti essere in grado di scoprire esattamente perché.

Altri suggerimenti

Informazioni sull'array. La linea

NSMutableArray *array = [NSMutableArray array];

in realtà non ti dà un oggetto mantenuto ma piuttosto un oggetto di rilascio automatico. Probabilmente viene trattenuto nella riga successiva ma non è necessario rilasciarlo nella terza riga. Vedi questo

  

Questa è la regola fondamentale:

     
    

Assumi la proprietà di un oggetto se lo crei utilizzando un metodo il cui nome inizia con "alloc" o "new" o contiene "copy" (ad esempio, alloc, newObject o mutableCopy) o se lo invii a conservare il messaggio. Sei responsabile della rinuncia alla proprietà degli oggetti di tua proprietà mediante rilascio o rilascio automatico. Ogni volta che ricevi un oggetto, non devi rilasciarlo.

  

In Xcode 4, puoi abilitare Zombi facendo clic sul menu a discesa Schema (in alto a sinistra, proprio accanto al pulsante di arresto) - > Modifica schema - > Scheda Diagnostica - > Abilita oggetti zombi

Xcode / gdb si interrompe sempre su EXC_BAD_ACCESS , devi solo risalire lo stack di chiamate per trovare il codice che lo ha attivato.

Si noti che questo tipo di errori si verificano spesso con oggetti rilasciati automaticamente , il che significa che la causa ultima del problema non sarà nello stack di chiamate che ha attivato EXC_BAD_ACCESS . Questo è quando NSZombieEnabled e NSAutoreleaseFreedObjectCheckEnabled diventano utili.

Una nuova risposta a un vecchio thread ... in XCode 4 il modo più efficace per diagnosticare le eccezioni EXC_BAD_ACCESS è utilizzare gli strumenti per profilare la tua app (da XCode fai clic su Prodotto / Profilo e scegli Zombi). Questo ti aiuterà a identificare i messaggi inviati agli oggetti deallocati.

Dalle classi CS193P di Stanford: se aggiungi un punto di interruzione (manualmente, modificando i punti di interruzione) per il simbolo objc_exception_throw puoi ottenere un'immagine molto migliore di ciò che è andato storto - lasciando che le cose procedano al punto dove il debugger si ferma da solo tende a oscurare le cose e rovinare la traccia dello stack. Quando ti fermi in objc_exception_throw puoi spesso guardare indietro a quale accesso / operazione ha causato il tuo problema.

Un altro approccio utile è impostare i punti di interruzione che verranno attivati ??direttamente dopo il verificarsi dell'eccezione:

  

Apri la finestra dei punti di interruzione (Esegui & # 8211; Mostra & # 8211; Punti di interruzione) e aggiungi due punti di interruzione simbolici chiamati & # 8220; objc_exception_throw & # 8221; e & # 8220; [aumento NSException] "

Da: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

Volevo solo aggiungere per gli altri che provengono da un web, alla ricerca di soluzioni per lo stesso errore ma con errore diverso. Nel mio caso ho avuto lo stesso errore quando ho provato a creare un'istanza di NSDictionary con errore di battitura nel nome della chiave in cui ho dimenticato di aggiungere " @ " davanti alla mia chiave:

NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];

Spero di non aver perso una risposta identica, ma ho scoperto che è possibile che alcuni progetti generino questo errore a causa dell'esecuzione su simulatori per versioni iOS precedenti che potrebbero essere incompatibili con una dipendenza o un framework di progetto. Stavo inseguendo uno di questi da troppo tempo prima di rendermi conto che stava succedendo solo nelle versioni più vecchie del simulatore, come iPhone 4S, che l'app non avrebbe nemmeno dovuto provare a supportare.

Sarebbe stato bello avere ricevuto un messaggio di errore più dettagliato, ma immagino che sia la responsabilità del framework in cui è nato ... Ad ogni modo, questo è un atterraggio di ricerca abbastanza comune e forse questo aiuterà qualcuno a scherzare su quanto male mi sono trovato.

Prima di abilitare gli zombi, ti consiglio di sbarazzarti di tutti gli avvisi (se ne hai). Cose semplici come una funzione non nulla senza un return possono causare questo errore. Se non hai avvisi, procedi come suggerito dalle altre risposte.

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