2015-07-18 10 views
7

Sto lavorando su un'applicazione per iPhone in Objective-C (con Xcode 6.1.1 e Parse), e ho appena ricevuto questo misterioso NSInternalInconsistencyException:Come trovare la fonte di un NSInternalInconsistencyException in un Xcode Stack Trace

Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.":

Quindi la mia domanda per la comunità Stack Overflow è:

Come fa qualcuno a leggere questo stack trace di dare la caccia la vera fonte del problema? Non vedo alcun nome di file riconoscibile, chiamate di metodo o numeri di riga in nessuna parte di questa traccia dello stack.

Oppure, se non si tratta semplicemente di leggere la traccia dello stack e altre tecniche sono coinvolte, qual è il passo successivo appropriato che uno sviluppatore dovrebbe intraprendere per rintracciare l'origine di questo tipo di errore?

Ecco la traccia dello stack completo che emette alla mia console:

 
2015-07-18 02:01:17.596 testapp[1276:60b] [Error]: Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.": 
(
    0 CoreFoundation      0x2f547f9b + 154 
    1 libobjc.A.dylib      0x39c94ccf objc_exception_throw + 38 
    2 CoreFoundation      0x2f547ec5 + 0 
    3 testapp        0x00205a29 -[PFObject(Private) resolveLocalId] + 384 
    4 testapp        0x00233d6d __32-[PFRESTCommand resolveLocalIds]_block_invoke + 24 
    5 testapp        0x00233783 +[PFRESTCommand forEachLocalIdIn:doBlock:] + 642 
    6 testapp        0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 
    7 CoreFoundation      0x2f484043 + 98 
    8 CoreFoundation      0x2f483f67 + 162 
    9 testapp        0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 
    10 testapp        0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 
    11 CoreFoundation      0x2f484043 + 98 
    12 CoreFoundation      0x2f483f67 + 162 
    13 testapp        0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 
    14 testapp        0x0023373f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 574 
    15 testapp        0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 
    16 CoreFoundation      0x2f484043 + 98 
    17 CoreFoundation      0x2f483f67 + 162 
    18 testapp        0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 
    19 testapp        0x00233ca3 -[PFRESTCommand forEachLocalId:] + 162 
    20 testapp        0x00233d3f -[PFRESTCommand resolveLocalIds] + 34 
    21 testapp        0x0023ee2f -[PFRESTCommandRunner _runCommandAsync:withCancellationToken:] + 110 
    22 testapp        0x0023e8c7 -[PFRESTCommandRunner runCommandAsync:withOptions:cancellationToken:] + 174 
    23 testapp        0x0023e7d7 -[PFRESTCommandRunner runCommandInBackground:inOperation:] + 42 
    24 testapp        0x00203667 __65+[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]_block_invoke_3 + 766 
    25 testapp        0x002854b3 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 214 
    26 libdispatch.dylib     0x3a17c833 + 10 
    27 libdispatch.dylib     0x3a183ad7 + 222 
    28 libdispatch.dylib     0x3a183d29 + 56 
    29 libsystem_pthread.dylib    0x3a2bebd3 _pthread_wqthread + 298 
    30 libsystem_pthread.dylib    0x3a2bea98 start_wqthread + 8 
). 

Apprezzo tutto l'aiuto e le intuizioni che mi può offrire.

risposta

4

Questo particolare esempio non offre molto allo sviluppatore. Quindi, la risposta alla tua domanda in questo caso è "Google it." In realtà, il miglior indizio dalla traccia dello stack è la linea:

[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:] 

La linea di cui sopra indica un fallito salvataggio utilizzando currentUser, in combinazione con il messaggio di errore "Tentativo di salvare un oggetto con un puntatore ad un nuovo, oggetto non salvato ". dovrebbe essere sufficiente per indicare una causa probabile.

Come risulta, questo errore non è raro ed è sconcertante perché Parse non lo risolva. Generalmente è causato da quando la tua app utilizza utenti Parse anonimi e tenta di salvare un oggetto prima che l'oggetto utente sia stato salvato. Poiché l'oggetto utente non è stato salvato, non ha objectId e il salvataggio dell'altro oggetto fallisce.

La soluzione è controllare se l'oggetto currentUser ha un objectId e, in caso contrario, salvarlo prima di provare a scrivere su Parse.

// Prevent race condition for unsaved user 
    // Courtesy of: http://samwize.com/2014/07/15/pitfall-with-using-anonymous-user-in-parse/ 
    if ([PFUser currentUser].objectId == nil) { 
     [[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { 
      //do stuff later 
     }]; 
    } else { 
     //do stuff now 
    } 
+0

Grazie. Questo mi ha aiutato ad andare nella giusta direzione. –

2

NSInternalInconsistencyException viene generato quando un codice entra in uno stato che non dovrebbe mai accadere. Di solito indica un bug creato da coloro che lo hanno scritto, anche se a volte è possibile causare tale condizione usando male la libreria (facendo qualcosa contro ciò che dicono i documenti, per esempio).

In altre parole, è un bug, ma se non hai scritto il codice che lo lancia, probabilmente non è tuo. Da questa particolare traccia di stack, il problema deve essere in Parse.

Segnala il bug agli sviluppatori originali. Una buona biblioteca non deve mai lanciarla, indipendentemente dal fatto che tu la stia abusando o meno. Fino a quando non lo risolvono, il meglio che puoi fare è provare a risolverlo, facendo ciò che stavi cercando di fare in un modo diverso. Se si dispone delle origini di tale libreria, è possibile provare a eseguire il debug e risolvere il problema da soli.

+0

Apprezzo la risposta, anche se avrei ancora bisogno di saper leggere questo stack trace per trovare le aree problematiche (nel mio codice o analizzare di) a seguire i vostri suggerimenti come * "fare quello che stavi cercando di fare in un modo diverso "* (come faccio a sapere cosa fare diversamente senza conoscere la causa?), oppure * "Se si dispone delle origini di tale libreria, si potrebbe provare a eseguire il debug e risolvere il problema da soli" * (come faccio a sapere come trovare il codice giusto da risolvere?). La mia domanda riguarda davvero "quali passi fare per trovare la fonte di questo errore", e poi da lì, posso seguire il tuo consiglio. Grazie ancora. –

+0

@IchigoKurosaki L'unico "passo" che viene in mente è quello di ri-simbolizzare la traccia dello stack (ad esempio usando lo strumento "atos') per ottenere i nomi dei file di origine e i numeri di riga per ciascun fotogramma. Non penso che possano esserci passi non specifici oltre a quello, perché la tua domanda è praticamente generale come "se ho un bug, come lo trovo?". – hamstergene

+0

Grazie per il vostro consiglio, ma ritengo che la mia domanda sia molto più specifica di "se ho un bug, come trovo?", Perché sto chiedendo "se ho una traccia di stack, come la leggo?" . La prima parte del tuo suggerimento era di ri-simbolizzare con lo strumento 'atos', che suona come una risposta utile. Potresti postare una risposta con alcuni dettagli su come qualcuno potrebbe usare questo strumento per ottenere più dettagli [leggibili] da una traccia stack? Perché una risposta del genere si sentirebbe pertinente alla domanda. Qualsiasi aiuto è apprezzato. –

Problemi correlati