objective-c iphone xcode debugging lldb

objective c - Xcode/LLDB: ¿Cómo obtener información sobre una excepción que acaba de lanzarse?



objective-c iphone (4)

El objeto de excepción se pasa como primer argumento a objc_exception_throw . LLDB proporciona $arg1 .. $argn variables para referirse a los argumentos en la convención de llamadas correcta, lo que facilita la impresión de los detalles de la excepción:

(lldb) po $arg1 (lldb) po [$arg1 name] (lldb) po [$arg1 reason]

Asegúrese de seleccionar el marco objc_exception_throw en la pila de llamadas antes de ejecutar estos comandos. Consulte "Depuración avanzada y el desinfectante de direcciones" en los videos de la sesión WWDC15 para ver esto en el escenario.

Información desactualizada

Si está en GDB, la sintaxis para referirse al primer argumento depende de las convenciones de llamada de la arquitectura en la que se está ejecutando. Si está depurando en un dispositivo iOS real, el puntero al objeto está en el registro r0 . Para imprimirlo o enviarle mensajes, use la siguiente sintaxis simple:

(gdb) po $r0 (gdb) po [$r0 name] (gdb) po [$r0 reason]

En el simulador de iPhone, todos los argumentos de función se pasan a la pila, por lo que la sintaxis es considerablemente más horrible. La expresión más corta que podría construir es: *(id *)($ebp + 8) . Para hacer las cosas menos dolorosas, sugiero usar una variable de conveniencia:

(gdb) set $exception = *(id *)($ebp + 8) (gdb) po $exception (gdb) po [$exception name] (gdb) po [$exception reason]

También puede establecer $exception automáticamente cada vez que se desencadena el punto de interrupción agregando una lista de comandos al punto de interrupción objc_exception_throw .

(Tenga en cuenta que en todos los casos que probé, el objeto de excepción también estaba presente en los registros eax y edx en el momento en que golpeó el punto de interrupción. Sin embargo, no estoy seguro de que siempre sea el caso).

Agregado de los comentarios a continuación:

En lldb , seleccione el marco de pila para objc_exception_throw y luego ingrese este comando:

(lldb) po *(id *)($esp + 4)

De acuerdo, imagina que mi punto de interrupción en objc_exception_throw acaba de objc_exception_throw . Estoy sentado en el indicador del depurador, y quiero obtener más información sobre el objeto de excepción. ¿Donde lo encuentro?


En el momento de escribir esto, esta publicación es mi principal éxito de Google para: lldb print exception . Por lo tanto, estoy agregando esta respuesta a la cuenta para lldb y x86_64.

Mis intentos de encontrar la excepción usando po $eax fallaron con el error: Couldn''t materialize struct: Couldn''t read eax (materialize) . Otros intentos descritos en documentos vinculados de respuestas anteriores también fallaron.

La clave fue que primero tuve que hacer clic en el marco objc_exception_throw en mi hilo principal. lldb no comienza en ese marco.

En todos mis ejemplos de búsqueda y siguientes, esta entrada de blog fue la primera en explicar las cosas de una manera que funcionó para mí. Es más moderno, publicado en agosto de 2012.


Si tiene una declaración de captura, coloque un punto de interrupción allí y puede inspeccionar el objeto de excepción en ese punto.

Si no tiene una declaración catch, continúe.

Recibirás un mensaje en tu terminal así:

Aplicación de terminación debido a excepción no detectada ''NSInvalidArgumentException'', razón: '' * - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: intento de insertar nil object desde objetos [0]''

Sin embargo , probablemente esté buscando una forma de inspeccionarlo sin continuar, ya que perderá su buen seguimiento de la pila cuando finalice la aplicación.

Para eso, parece que la respuesta de Fnord es la mejor, pero no pude hacerlo funcionar en LLDB.


en nuevos simuladores (iOS 8, 64 bits) xcode 6 im usando en el marco de excepción: objc_exception_throw

po $rax

en 32 bits:

po $eax

¿Qué es rax?

Rax es un registro de 64 bits que reemplaza el viejo eax

¿Cómo encontrar todos los registros?

register read

Fuente wikipedia