2009-01-22 20 views
6

Ecco il mio caso: ho una vista tabella che mostra i contatti. Il pulsante Aggiungi nella barra di navigazione viene utilizzato per caricare un'altra vista per l'immissione dei dati. Questa nuova vista ha le immagini nell'intestazione della tabella e ogni cella di tabella ha un UITextField o un UITextView. Quando premo Annulla, la vista viene espulsa e la memoria viene rilasciata.Sviluppo iPhone - errore EXC_BAD_ACCESS senza traccia stack

Ecco il mio problema: quando apro l'interfaccia "Aggiungi", fornire un valore in una qualsiasi delle UITextField o UITextView, e premere il tasto "Annulla" per tornare alla vista primaria, ottengo un errore EXC_BAD_ACCESS. Quando lo rintraccia, il "Aggiungi controller" chiama dealloc correttamente, ma dopo il [super dealloc] quando si preme Continua, genera questo errore. Solo questo, nessuna traccia, anche se sto usando NSZombieEnabled. Quando eseguo il codice con strumenti, non ottengo alcun errore :(

Spero di essere stato chiaro nello spiegare il problema. Qualsiasi puntatori? Grazie.

+0

Il problema scompare magicamente quando rimuovo [rilascio tableView] dalla mia "Aggiungi contatto" Metodo dealloc della classe Controller. Ma dovrei rilasciare l'oggetto tableView, giusto? Anche se sto usando il file pennino - e reso tableView un 'IBOutlet'. – Mustafa

+1

No, non dovresti. La regola da ricordare è "Se non l'hai allocata, copiata o conservata esplicitamente, allora non la rilascerai esplicitamente". –

risposta

8

La causa più comune di questo errore è quando rilasci un oggetto e qualche altro meccanismo prova ad accedere/rilasciarlo/deallocarlo più tardi.

Ogni volta che ottengo un rapporto su un errore EXC_BAD_ACCESS, la mia prima raccomandazione è di scorrere il codice per determinare quale linea lo sta causando, e quindi per cercare qualsiasi chiamata esplicita di [object release] che faccia riferimento a quell'oggetto. Commentale uno per uno per scoprire dove potresti aver sbagliato (e, ovviamente, assicurati di l'oggetto è correttamente rilasciato in seguito).

Se la linea non aiuta a capire quale/i oggetto/che sta causando il problema, inizia a guardare attraverso le tue chiamate [object release] e assicurati di non rilasciare oggetti troppe volte accidentalmente o di rilasciare oggetti che non possiedi.

Questo porta ad una buona linea guida generale per quanto riguarda release in Objective-C:

Se si possiede un oggetto (o allocare conservarlo), lo si rilascia. Se non lo possiedi (è venuto tramite il metodo di convenienza o qualcun altro lo ha assegnato), non lo rilasci.

(Via Memory Management with Objective C/Cocoa/iPhone, che ha anche alcuni buoni consigli.)

1

La regola generale è che nulla si crea, è necessario gestire (mantenere/release). Tutto ciò che esce da un NIB, in genere non dovrebbe essere rilasciato in codice.

3

Inserire il [super dealloc] come ultima istruzione del metodo dealloc della classe. Avrai questo comportamento quando avrai dealloc la super classe prima.

6

Sebbene questo sia il più delle volte il risultato di una memoria mal gestita, può accadere per altri motivi (ed è più difficile eseguire il debug che semplicemente attivare NSZombieEnabled). Ad esempio, se non si riesce a fornire il numero corretto di argomenti a una stringa di formato (ad esempio durante il debug di un altro problema con NSLog), si potrebbe finire senza traccia di stack anche con tutti gli argomenti di debug abilitati. Fortunatamente, è possibile utilizzare GDB all'interno di Xcode su restore the stack trace to a previous state.

Nella console GDB dovresti vedere le istruzioni che hanno causato il crash del tuo programma. Trova l'ultima istruzione di ritorno con successo prima di quella che ha fallito.Esso dovrebbe essere simile a questo:

je 0x986cef35 <objc_msgSend+117> 

Nota il valore esadecimale ed eseguire il seguente in GDB:

set $eip = 0x986cef35 
stepi 
where 

Si dovrebbe (si spera) avere una traccia dello stack più informativo ora.

Source (lo stesso link qui sotto)

+0

Il [collegamento] (http://www.mulle-kybernetik.com/weblog/2010/07/exc_bad_access_and_no_stack_tr.html) non funziona. Ecco il [aggiornato] (http://www.mulle-kybernetik.com/weblog/2010/exc_bad_access_and_no_stack_tr.html) uno – BLC

1

Le dichiarazioni di cui sopra che non si deve rilasciare gli oggetti NIB sono contraddette da Apple: vedi here, in cui si dice che gli oggetti per i quali si dispone di una presa di corrente dovrebbero essere rilasciati in dealloc e anche che dovresti assicurarti di impostare il riferimento all'oggetto su nil in seguito.

Disclaimer: Sono un principiante della programmazione iPhone, anche se ho programmato da molto tempo.

2

La risposta di Cameron Spickert è un po 'deprecata, dal momento che Xcode usa lldb ora anziché gdb. Anche il link all'articolo sorgente è morto.

La stessa cosa può essere fatto piuttosto semplicemente con il seguente comando lldb:

(lldb) thread backtrace 

Questo mostrerà il bt per il thread corrente. Se si desidera cambiare il filo da cui si desidera ottenere il bt, selezionare la cornice e ottenere in questo modo:

(lldb) thread list 
(lldb) thread select 2 
(lldb) thread backtrace 

Se si desidera replicare l'esatto comportamento di risposta di Cameron Spickert, utilizzare i seguenti comandi:

(lldb) expr unsigned int $eip = 0x1979c81d4 
(lldb) stepi 
(lldb) thread backtrace 

Source 1

Source 2

Problemi correlati