Xcode no muestra la línea que causa un bloqueo

126

Cada vez que mi aplicación falla, Xcode resalta la llamada UIApicationMain () en la función main () como la línea que causó el bloqueo. En algunos casos, eso solía ser normal (error de segmentación, por ejemplo), pero el bloqueo con el que estoy tratando de lidiar es un simple SIGABRT con información detallada registrada en la consola:

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

Xcode solía mostrar la línea correcta con SDK anteriores, pero desde que actualicé a Xocde 4.2 eso cambió. Es bastante obvio que Xcode sabe exactamente qué causó el bloqueo (o podría saberlo), pero aún no muestra la línea real. ¿Hay alguna solución o solución para esto?

JonasG
fuente
2
¿Estás compilando para el lanzamiento? Si es así, intente configurar el esquema en Depurar.
epatel
También podría ser que algo de xib sea malo y que el programa se bloquee en un lugar fuera de su propio código fuente, por lo tanto, no muestre ningún archivo. El error describe un problema para una clave de diccionario llamada "Fecha"
epatel
1
Apple debería contratar más probadores;)
Amr Lotfy

Respuestas:

301

También debe asegurarse de tener puntos de interrupción establecidos para todas las excepciones. Esto hará que Xcode se detenga en la línea donde se produce la excepción. Haga lo siguiente [en Xcode 4]:

  1. En el Navegador de proyectos en el lado izquierdo de Xcode, haga clic en el navegador del punto de interrupción (casi hasta el lado derecho de la barra de botones superior. El icono se ve como una gruesa flecha hacia la derecha).

  2. En la parte inferior del navegador, haga clic en el botón "+".

  3. Haga clic en "Agregar punto de interrupción de excepción".

  4. Se creará un nuevo punto de interrupción. Debe configurarse según sea necesario, pero puede modificar su comportamiento.

  5. Ejecute su proyecto y reproduzca la excepción.

También mencionó que se vinculó a algunas bibliotecas / marcos de terceros. Si la excepción se produce dentro de esos marcos, tendrá dificultades ya que el código se compila y Xcode no puede mostrarle la línea que causó la excepción. Si este es el caso y está seguro de que está utilizando las bibliotecas correctamente, debe presentar un informe de error a los encargados del mantenimiento de esas bibliotecas.

Carretero
fuente
44
Soy un novato y desarrollé casi un mes sin esto ... esto cambia mi vida.
Jonny Burger
44
Mi amigo se registró para una cuenta SO solo para votar esta publicación.
Alex Spencer
1
esto se llama medio asno en las manzanas parte de mi libro
ChuckKelly
1
Hice esto, pero aún no puede encontrar dónde llamó la longitud en un valor nulo :(
Shereef Marzouk
1
Esto funciona, pero la desventaja es que ya no genera detalles de la excepción en la consola de depuración. Entonces, puedo APAGAR este punto de interrupción y ver detalles y trazas de la excepción, pero no DONDE sucedió, o ENCENDERLO para ver dónde sucedió, pero sin POR QUÉ. Alguien sabe cómo tener ambos?
Gabriel Jensen el
27

Simplemente siga las instrucciones en esta respuesta de StackOverflow:

Habilitar zombis

Básicamente, solo necesitas "Habilitar zombis". Entonces Xcode debería romperse en cualquier línea que haya causado el problema.

ingrese la descripción de la imagen aquí

(Es absolutamente impactante que, incluso en 2017, Xcode todavía tenga esto desactivado de forma predeterminada. ¿Por qué no querría ver la línea que causó el problema? ¿Y " Habilitar objetos zombis "? ¡¿En serio?! ¿cree que este es un nombre útil, que tendría algún tipo de sentido para los nuevos desarrolladores? Es deprimente cuán pobre es la calificación de Xcode, año tras año, en la App Store. Nadie está escuchando ...)

Mike Gledhill
fuente
66
Xcode es el peor entorno de programación que he usado hasta ahora.
Estudiante
Lo que me parece interesante (como desarrollador de Visual Studio) es cuántos desarrolladores de Xcode he conocido, que insisten en que Xcode es el mejor entorno que han usado. Lógico, amable y servicial ... pero con algunas peculiaridades. Incluso ahora, en noviembre de 2019, Xcode tiene una calificación de App Store de 3.1, y la mayoría de las personas le otorgan 5 estrellas o 1 estrella. Nadie está escuchando ...
Mike Gledhill
9

Editar el esquema actual y habilitar NSZombieEnabled, MallocStackLoggingy guard malloc. Luego, cuando su aplicación falla, escriba esto en la consola gdb:

(gdb) info malloc-history 0x543216

Reemplace 0x543216con la dirección del objeto que causó el NSInvalidArgumentExceptiony debería darle un seguimiento de pila mucho más útil, mostrando las líneas de su código que están causando el bloqueo.

chown
fuente
1
Intenté esto y recibí el error: 'info' no es un comando válido. ¿Algún consejo?
achi
@EliGregory asegúrese de que su depurador esté configurado en gdb y no en el lldb predeterminado. Puede cambiarlo en el menú Editar esquema en la sección Ejecutar.
Chown
2

He visto este comportamiento en código muy optimizado; comprobar, ajustar el nivel de optimización de su objetivo y los de las librerías de terceros puede ayudar. (Configuración del nivel de optimización de LLVM 3.0)

¿Estás generando símbolos de depuración?

FluffulousChimp
fuente
Convenido. Si está intentando depurar, entonces el nivel de optimización debe establecerse en 0 (Sin optimización) en la configuración de compilación.
Carter
1

Escribí código para generar un bloqueo de índice fuera del límite. A continuación se presenta la excepción.

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

Si lees atentamente First Throw call stack

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

0 and 1 son los procesos del sistema después del bloqueo.

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

2 es la línea que causó la excepción.

3   testABC                     0x000000010dce962d -[ViewController ComplexFunction] + 61

3le dice que el nombre de clase ( ViewController) y la función naem ( ComplexFunction) en la que se produjo la excepción.

AsifHabib
fuente
44
Errr, está bien. Tienes toda la razón, pero ¿es amigable? En cualquier entorno de desarrollo moderno (de 1990 en adelante), cuando se produce una excepción, se lo dirige a la línea que causó el problema. Mientras que Xcode ... bueno ... te da un seguimiento de la pila como este. ¡Incluso Turbo Pascal no estaba tan anticuado!
Mike Gledhill
44
Es ridículo que la compañía que supuestamente es conocida por la "mejor experiencia de usuario" no se da cuenta de que todos los desarrolladores de los últimos 20 años están acostumbrados a ver el número de línea donde se produce una excepción y NO EN EL ASAMBLEADOR. ¿Me estoy volviendo loco? Cada idioma con el que he trabajado toda mi vida da números de línea. Incluso C o C ++.
mylovemhz