2011-10-09 8 views
109

Ogni volta che l'app si arresta in modo anomalo Xcode evidenzia la chiamata a UIApicationMain() nella funzione main() come la linea che ha causato l'arresto. In alcuni casi, che hanno usato per essere normale (errore di segmentazione per esempio), ma l'incidente che sto cercando di affrontare è un semplice SIGABRT con informazioni dettagliate registrati nella console:Xcode non mostra la linea che causa un crash

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: Date)' 

Xcode utilizzato per mostrare la linea giusta con gli SDK precedenti ma da quando ho aggiornato a Xocde 4.2 che è cambiato. È ovvio che Xcode sa esattamente cosa ha causato il crash (o potrebbe saperlo), ma non mostra ancora la linea attuale. C'è qualche soluzione o soluzione per questo?

+2

Si sta compilando per la versione? Se è così prova a impostare lo schema su Debug. – epatel

+0

È impostato per eseguire il debug. – JonasG

+0

Potrebbe anche darsi che qualche xib sia cattivo causando il crash del programma in un posto fuori dal proprio codice sorgente, quindi, non mostrando alcun file. L'errore descrive un problema per una chiave dizionario denominata "Data" – epatel

risposta

275

È inoltre necessario assicurarsi di disporre di punti di interruzione impostati per tutte le eccezioni. Ciò causerà l'arresto di Xcode nella riga in cui si verifica l'eccezione. Effettuare le seguenti operazioni [in Xcode 4]:.

  1. nella navigazione di progetto sul lato sinistro di Xcode, clicca sul navigatore punto di interruzione (quasi tutta la strada sul lato destro della barra dei pulsanti in alto l'icona sembra una grossa freccia destra).

  2. Nella parte inferiore del navigatore, fare clic sul pulsante "+".

  3. Fare clic su "Aggiungi punto di interruzione eccezione".

  4. Un nuovo punto di interruzione verrà creato. Dovrebbe essere configurato in base alle esigenze, ma è possibile modificarne il comportamento.

  5. Esegui il tuo progetto e riproduci l'eccezione.

Inoltre hai menzionato che ti sei collegato ad alcune librerie/framework di terze parti. Se si verifica un'eccezione all'interno di tali framework, si avrà un momento difficile dal momento che il codice è stato compilato e Xcode non può effettivamente mostrare la linea che ha causato l'eccezione. Se questo è il tuo caso e sei certo che stai usando le librerie correttamente, allora dovresti presentare una segnalazione di bug ai manutentori di quelle librerie.

+6

ciao, ho provato la soluzione, ma la prende su Main nuovo .. – Dejell

+0

No, scegliere "On Throw", altrimenti lo farà prendere il punto di interruzione su main. –

+5

Questa risposta, come scritto, è corretta per Xcode 5. –

2

Ho visto questo comportamento in codice fortemente ottimizzato; il controllo, il tweaking del livello di ottimizzazione del target e quelli delle librerie di terze parti possono essere d'aiuto. (Impostazione del livello di ottimizzazione LLVM 3.0)

Stai generando i simboli di debug?

+0

concordato. Se stai tentando di eseguire il debug, il livello di ottimizzazione deve essere impostato su 0 (Nessuna ottimizzazione) nelle impostazioni di generazione. – Carter

7

Modificare lo schema corrente e abilitare NSZombieEnabled, MallocStackLogging e guard malloc. Poi, quando la vostra applicazione si blocca, digitare questo nella console gdb:

(gdb) info malloc-history 0x543216 

Sostituire 0x543216 con l'indirizzo dell'oggetto che ha causato la NSInvalidArgumentException e dovrebbe dare una molto più utile analisi dello stack, che mostra le linee del vostro codice che causa l'arresto anomalo.

+0

Ho provato questo, ed è stato generato l'errore: 'info' non è un comando valido. Qualche consiglio? – achi

+0

@EliGregory assicurati che il tuo debugger sia impostato su gdb e non su lldb predefinito. Puoi cambiarlo nel menu Modifica schema sotto la sezione Esegui. – chown

14

Basta seguire le istruzioni su questa risposta StackOverflow:

Enable Zombies

In sostanza, non vi resta che "Attiva Zombies". Quindi Xcode dovrebbe rompere a seconda di quale linea ha causato il problema.

enter image description here

(è assolutamente scioccante che, anche nel 2017, Xcode ha ancora questo disattivato per default. Perché si non vogliono vedere la riga che ha causato il problema? E "Abilita Zombie Oggetti "?! Davvero?! Gli autori di Xcode credono davvero che questo sia un nome utile, che potrebbe dare un senso ai nuovi sviluppatori? È deprimente quanto sia scarso il rating di Xcode, anno dopo anno, nell'App Store. nessuno è in ascolto ...)

+0

Così vero ... Lontano dietro Visual Studio in tanti modi. – Brduca

+2

Un grande punto, MikeGledhill. – Fattie

0

ho scritto codice per generare un crash di indice fuori limite. Segue l'eccezione generata.

2017-01-07 04:02:57.606 testABC[1694:52966] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' 
*** First throw call stack: 
(
    0 CoreFoundation      0x000000010e85cd4b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x000000010e2be21e objc_exception_throw + 48 
    2 CoreFoundation      0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111 
    3 testABC        0x000000010dce962d -[ViewController ComplexFunction] + 61 
    4 testABC        0x000000010dce95db -[ViewController thirdFunction] + 43 
    5 testABC        0x000000010dce959b -[ViewController secondFunction] + 43 
    6 testABC        0x000000010dce955b -[ViewController firstFinction] + 43 
    7 testABC        0x000000010dce96c2 -[ViewController viewDidAppear:] + 50 
    8 UIKit        0x000000010ee28a6c -[UIViewController _setViewAppearState:isAnimating:] + 945 
    9 UIKit        0x000000010ee2b7da __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 42 
    10 UIKit        0x000000010ee29ac4 -[UIViewController _executeAfterAppearanceBlock] + 86 
    11 UIKit        0x000000010ec8d77c _runAfterCACommitDeferredBlocks + 653 
    12 UIKit        0x000000010ec7a273 _cleanUpAfterCAFlushAndRunDeferredBlocks + 566 
    13 UIKit        0x000000010ec9d757 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke_2 + 194 
    14 CoreFoundation      0x000000010e8016ac __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 
    15 CoreFoundation      0x000000010e7e66f4 __CFRunLoopDoBlocks + 356 
    16 CoreFoundation      0x000000010e7e5e65 __CFRunLoopRun + 901 
    17 CoreFoundation      0x000000010e7e5884 CFRunLoopRunSpecific + 420 
    18 GraphicsServices     0x00000001126d9a6f GSEventRunModal + 161 
    19 UIKit        0x000000010ec80c68 UIApplicationMain + 159 
    20 testABC        0x000000010dce99df main + 111 
    21 libdyld.dylib      0x000000011174968d start + 1 
    22 ???         0x0000000000000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

Se si legge con attenzione il First Throw call stack

0 CoreFoundation    0x000000010e85cd4b __exceptionPreprocess + 171 
1 libobjc.A.dylib    0x000000010e2be21e objc_exception_throw + 48 

0 and 1 sono i processi del sistema dopo l'incidente.

2 CoreFoundation    0x000000010e8b5c2f -[__NSSingleObjectArrayI objectAtIndex:] + 111 

2 è la linea che ha causato l'eccezione.

3 testABC      0x000000010dce962d -[ViewController ComplexFunction] + 61 

3 ti dice che il nome di classe (ViewController) e la funzione naem (ComplexFunction), in cui è stato gettato un'eccezione.

+1

Errr, ok. Hai assolutamente ragione, ma è così amichevole? In qualsiasi ambiente di sviluppo moderno (dagli anni '90 in poi), quando si verifica un'eccezione, vieni indirizzato alla linea che ha causato il problema. Mentre Xcode ... beh ... ti dà una traccia di stack come questa. Anche Turbo Pascal non era obsoleto !!! –

+0

È ridicolo che la società che è presumibilmente conosciuta per la "migliore esperienza utente" non si renda conto che tutti gli sviluppatori negli ultimi 20 anni sono abituati a vedere il numero di riga dove viene generata un'eccezione e NON IN ASSEMBLER. Sto impazzendo? Ogni lingua che abbia mai lavorato con tutta la mia vita dà numeri di linea. Anche C o C++. – mylovemhz