OK, imagine que meu ponto de interrupção objc_exception_throw
acabou de ser acionado. Estou sentado no prompt do depurador e quero obter mais informações sobre o objeto de exceção. Onde posso encontrar?
OK, imagine que meu ponto de interrupção objc_exception_throw
acabou de ser acionado. Estou sentado no prompt do depurador e quero obter mais informações sobre o objeto de exceção. Onde posso encontrar?
Respostas:
O objeto de exceção é passado como o primeiro argumento para objc_exception_throw
. O LLDB fornece $arg1
.. $argn
variáveis para se referir a argumentos na convenção de chamada correta, tornando simples imprimir os detalhes da exceção:
(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
Certifique-se de selecionar o objc_exception_throw
quadro na pilha de chamadas antes de executar esses comandos. Veja "Depuração Avançada e Sanitizador de Endereços" nos vídeos da sessão WWDC15 para ver como isso é realizado no palco.
Informação Desatualizada
Se você estiver no GDB, a sintaxe para se referir ao primeiro argumento depende das convenções de chamada da arquitetura em que você está executando. Se você estiver depurando em um dispositivo iOS real, o ponteiro para o objeto está registrado r0
. Para imprimi-lo ou enviar mensagens para ele, use a seguinte sintaxe simples:
(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]
No iPhone Simulator, todos os argumentos de função são passados na pilha, portanto, a sintaxe é consideravelmente mais horrível. A expressão mais curta que eu poderia construir é *(id *)($ebp + 8)
. Para tornar as coisas menos dolorosas, sugiro o uso de uma variável de conveniência:
(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]
Você também pode definir $exception
automaticamente sempre que o ponto de interrupção é acionado, adicionando uma lista de comandos aoobjc_exception_throw
ponto de interrupção.
(Observe que em todos os casos que testei, o objeto de exceção também estava presente no eax
e se edx
registra no momento em que o ponto de interrupção atingiu. Não tenho certeza se esse será sempre o caso.)
Adicionado a partir do comentário abaixo:
No lldb , selecione o frame da pilha objc_exception_throw
e insira este comando:
(lldb) po *(id *)($esp + 4)
objc_exception_throw
em LLDB : po *(id *)($esp + 4)
.
objc_exception_throw
).
po $eax
funciona para mim no simulador como pendente para o $r0
dispositivo quando.
em novos simuladores (iOS 8, 64 bits) xcode 6 im usando no quadro de exceção: objc_exception_throw
po $rax
em 32 bits:
po $eax
O que é rax?
Rax é um registrador de 64 bits que substitui o antigo eax
Como encontrar todos os registros?
register read
No momento em que este artigo foi escrito, este post é meu principal hit no Google para: exceção de impressão lldb . Portanto, estou adicionando esta resposta para explicar o lldb e o x86_64.
Minhas tentativas de encontrar a exceção usando po $eax
falharam com error: Couldn't materialize struct: Couldn't read eax (materialize)
. Outras tentativas descritas em documentos vinculados de respostas anteriores também falharam.
O segredo era que eu precisava primeiro clicar no objc_exception_throw
quadro do meu tópico principal. O lldb não começa nesse quadro.
Em todos os meus exemplos de pesquisa e seguimento, esta entrada do blog foi a primeira a explicar as coisas de uma maneira que funcionou para mim. É mais moderno, tendo sido postado em agosto de 2012.
Se você tiver uma instrução catch, coloque um ponto de interrupção lá e você poderá inspecionar o objeto de exceção nesse ponto.
Se você não tiver uma instrução catch, continue.
Você receberá uma mensagem em seu terminal como esta:
Encerrando aplicativo devido à exceção não capturada 'NSInvalidArgumentException', motivo: ' * - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: tentativa de inserir objeto nulo de objetos [0]'
Contudo , você provavelmente está procurando uma maneira de inspecioná-lo sem continuar, já que perderá seu bom rastreamento de pilha quando o aplicativo for encerrado.
Para isso, parece que a resposta do Fnord é a melhor, mas não consegui fazê-la funcionar no LLDB.