Xcode / LLDB : 방금 발생한 예외에 대한 정보를 얻는 방법은 무엇입니까?


83

좋아요, 내 중단 점이 objc_exception_throw방금 트리거 되었다고 상상해보세요 . 디버거 프롬프트에 앉아 예외 개체에 대한 추가 정보를 얻고 싶습니다. 어디서 찾을 수 있나요?


2
예외가 방금 발생했으며 설명이 아직 콘솔에 인쇄되지 않았습니다.
Karoy Lorentey

이 질문을 확인하십시오 : stackoverflow.com/questions/711650
Nikolai Fetissov

답변:


162

예외 개체는에 대한 첫 번째 인수로 전달됩니다 objc_exception_throw. LLDB는 올바른 호출 규칙에서 인수를 참조하는 $arg1.. $argn변수를 제공 하므로 예외 세부 정보를 간단하게 인쇄 할 수 있습니다.

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

objc_exception_throw이러한 명령을 실행하기 전에 호출 스택에서 프레임 을 선택해야 합니다. 무대에서 수행되는 작업을 보려면 WWDC15 세션 비디오의 "Advanced Debugging and the Address Sanitizer"를 참조하십시오.

오래된 정보

GDB를 사용하는 경우 첫 번째 인수를 참조하는 구문은 실행중인 아키텍처의 호출 규칙에 따라 다릅니다. 실제 iOS 기기에서 디버깅하는 경우 객체에 대한 포인터는 register에 r0있습니다. 인쇄하거나 메시지를 보내려면 다음과 같은 간단한 구문을 사용하십시오.

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

iPhone Simulator에서는 모든 함수 인수가 스택에 전달되므로 구문이 훨씬 더 끔찍합니다. 내가 만들 수있는 가장 짧은 표현은 *(id *)($ebp + 8). 일을 덜 고통스럽게 만들기 위해 편의 변수를 사용하는 것이 좋습니다.

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

$exception중단 점에 명령 목록을 추가하여 중단 점이 트리거 될 때마다 자동으로 설정할 수도 있습니다 objc_exception_throw.

(내가 테스트 한 모든 경우에서 예외 객체는 중단 점에 도달 할 때 eaxedx레지스터 에도 존재했습니다 . 그래도 항상 그런 경우는 아닙니다.)

아래 댓글에서 추가되었습니다.

에서 lldb 에 대한 스택 프레임을 선택 objc_exception_throw하고이 명령을 입력 :

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

6
lldb에서 어떻게할까요? "오류 : 'id'에 대한 참조가 모호합니다."라는 오류 메시지가 나타납니다.
offex

2
이 정보의 출처를 제공 할 수 있습니까? 나는 그것에 대해 자세한 내용을 싶습니다
주앙 Nunes 보낸 사람에게

3
현재 프롤로그 전에 나를 위해 다음과 같은 작품에 breaing 경우 objc_exception_throw LLDB : po *(id *)($esp + 4).
wbyoung

7
이것은 효과가 있었다! 그러나 스택 프레임 0을 선택할 때까지 작동하지 않았습니다 . ( objc_exception_throw).
funroll 2013 년

7
po $eax시뮬레이터 $r0에서 장치에있을 때 펜던트로 작동 합니다.
monkeydom

10

새 시뮬레이터 (iOS 8, 64 비트) xcode 6 im 예외 프레임에서 사용 : objc_exception_throw

po $rax

32 비트 :

po $eax

Rax는 무엇입니까?

Rax는 이전 eax를 대체하는 64 비트 레지스터입니다.

모든 레지스터를 찾는 방법은 무엇입니까?

register read

소스 위키 백과


흠 ... Xcode 6.1에서 다음과 같은 메시지가 나타납니다. (lldb) po $ rax error : could n't materialize : could n't read the value of register rax
Errored

@bradheintz 시뮬레이터 또는 장치? 나는 6.0.1로 이것을 시도했다
João Nunes

그것에 대한 귀하의 출처에 대한 링크를 제공 할 수 있습니까? 감사!
Chris Conover 2014 년

방금 lldb에 썼습니다 : register read. 그런 다음이 정보를 통해 예외 프레임의 첫 번째 레지스터에 예외 메시지가 있음을 알 수 있습니다.
João Nunes

Ok i found some docs : rax is a 64bits register : 64-bit long mode에서는 64 비트 레지스터를 사용할 수 있습니다 (예 : eax 대신 rax, ebx 대신 rbx 등)
João Nunes

6

이 글을 쓰는 시점에서이 게시물은 lldb print exception에 대한 Google 최고의 히트작입니다 . 따라서 lldb 및 x86_64를 설명하기 위해이 답변을 추가하고 있습니다.

를 사용하여 예외를 찾으려는 시도가 po $eax실패했습니다 error: Couldn't materialize struct: Couldn't read eax (materialize). 이전 답변의 링크 된 문서에 설명 된 다른 시도도 실패했습니다.

핵심은 objc_exception_throw메인 스레드 의 프레임 을 먼저 클릭해야한다는 것 입니다. lldb 는 해당 프레임에서 시작되지 않습니다.

내 모든 검색 및 다음 예제 에서이 블로그 항목 은 나를 위해 일한 방식으로 일을 설명하는 첫 번째 항목 이었습니다. 더 현대적이며 2012 년 8 월에 게시됩니다.


1

catch 문이있는 경우 거기에 중단 점을 입력하면 해당 지점에서 예외 개체를 검사 할 수 있습니다.

catch 문이 없으면 계속하십시오.

다음과 같은 메시지가 터미널에 표시됩니다.

포착되지 않은 예외 'NSInvalidArgumentException'으로 인해 앱 종료, 이유 : ' * -[__ NSPlaceholderDictionary initWithObjects : forKeys : count :] : 개체에서 nil 개체 삽입 시도 [0]'

그러나 응용 프로그램이 종료되면 멋진 스택 추적을 잃게되므로 계속하지 않고 검사 할 방법을 찾고있을 것입니다.

이를 위해 Fnord의 답변이 가장 좋은 것처럼 들리지만 LLDB에서 작동하지 못했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.