Xcode 4.2 디버그는 스택 호출을 상징하지 않습니다


140

iOS 5 시뮬레이터 / 장치에서 Xcode 4.2 디버깅에 문제가 있습니다. 예상대로 다음 코드가 충돌합니다.

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

iOS 4에서는 16 진수의 유용한 스택 추적을 얻습니다. 그러나 iOS 5에서는 다음을 제공합니다.

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

감사.

답변:


256

iOS 5 업데이트를 위해 XCode를 업그레이드 한 후 스택 추적이 작동하지 않는 것 같습니다.

그러나 효과적인 해결 방법을 찾았습니다. 내 자신의 예외 처리기를 만듭니다 (다른 이유로도 유용합니다). 먼저, 오류를 처리하고 콘솔로 출력하는 기능을 작성하십시오 (원하는 다른 작업).

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

그런 다음 앱 델리게이트에 예외 핸들러를 추가하십시오.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

그게 다야!

이것이 작동하지 않으면 가능한 두 가지 이유가 있습니다 .

  1. NSSetUncaughtExceptionHandler통화를 덮어 쓰고 있습니다 (전체 앱에 대해 하나의 핸들러 만있을 수 있음). 예를 들어 일부 타사 라이브러리는 자체 uncaughtExceptionHandler를 설정합니다. 따라서 didFinishLaunchingWithOptions기능 의 끝에서 설정 하거나 타사 라이브러리를 선택적으로 비활성화하십시오. 또는 더 좋은 방법은 상징적 인 중단 점을 설정하여 NSSetUncaughtExceptionHandler누가 전화했는지 신속하게 확인하는 것입니다. 당신이하고 싶은 것은 다른 것을 추가하는 것이 아니라 현재 것을 수정하는 것입니다.
  2. 실제로 예외가 발생하지 않습니다 (예 : 예외 EXC_BAD_ACCESS아닙니다 . 아래 @Erik B의 의견에 대한 신용)

1
기뻐요 :) 충돌 로그를 파일에 작성하고 다음에 시작할 때 파일을 제출하라는 메시지를 표시하는 것이 유용하다는 것을 알았습니다 (릴리스 모드에서만 디버깅 방법이 아님). 이것은 나에게 좋은 버그 리포트를 얻을 수 있습니다 ... 그리고 사용자 : 자신의 문제가 해결되고 있음을 알
젠 Claes가에게

2
이것은 작동하지 않는 것 같습니다- uncaughtExceptionHandler루틴이 호출되지 않습니다.
핫 릭

1
사용 방법에 대해 더 구체적으로 말씀해 주시겠습니까? 그것은 나를 위해 작동하지 않는 것 같습니다.
Danut Pralea

1
꽤 슬픈 xCode는 이것을 우리에게 표시하지 않습니다.
Authman Apatira

1
매우 감사! 애플이 이런 종류의 기본 기능을 IDE에 구현하지 않았다는 것은 당혹 스럽다.
devios1

110

예외 중단 점을 추가하는 유용한 옵션이 있습니다 (중단 점 탐색기 맨 아래에있는 + 사용). 이것은 모든 예외에서 중단됩니다 (또는 조건을 설정할 수 있습니다). 이 선택이 4.2에서 새로운 것인지 또는 마지막으로 누락 된 기호 문제를 해결하려고 시도하는 것을 알았는지 모르겠습니다.

이 중단 점에 도달하면 디버그 네비게이터를 사용하여 평상시처럼 호출 스택을 탐색하고 변수를 검사 할 수 있습니다.

복사 / 붙여 넣기 등에 적합한 기호화 된 호출 스택을 원하는 경우 gdb 역 추적은 다음과 같이 작동합니다.

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(기타)


3
이것은 지금까지 완벽하게 작동합니다. 디버거는 이제 충돌 라인에서 중단되므로 백 트레이스가 필요하지 않습니다.
Tim

1
이것은 나에게도 완벽하게 작동합니다. 나는 ...이 중단없이 정신을 가고 있었다, 정말 감사합니다
윌리엄 Denniss

효과가 +1되었습니다. 예외의 이유를 설명하는 멋진 오류 메시지를 제공하지는 않지만 시작입니다.
Nicu Surdu

당신은 내 HotD @WiseOldDuck입니다.
Maverick 1st

이것은 나에게 예상되는 동작을 복원합니다. 참고 : 새 프로젝트에서이 중단 점을 다시 추가해야합니다!
MechEthan

46

디버거에 새로운 기능이 있습니다. 4.0에서 발생했던 것처럼 예외가 발생할 때마다 중단 점을 설정하고 바로 실행을 중지 할 수 있습니다.

"Breakpoint Navigator"에서 "Exception Breakpoint"를 추가하고 옵션 팝업에서 "Done"을 누르십시오.

그게 다야!

추신 : 경우에 따라 Objective-C 예외에 대해서만 중단하는 것이 좋습니다.


분명히 이것은 나를위한 해결책입니다.
bradgonesurfing

이것은 나에게 문제였습니다. 동료와 저는 동일한 Xcode 프로젝트를 공유하고 문제가 있는지 물어 보았습니다. 차이점은 그의 프로젝트가 objective-c 예외 (objc_exception_throw)에서 깨어났다는 것입니다.
horseshoe7

추적 할 수없는 버그를 찾는 데 도움이되었습니다. 정말 고맙습니다. 나는 이와 같은 것을 사방에서 찾고 있습니다.
rjgonzo

1
이것은 매력처럼 작동합니다! 정확히 내가 찾던 것이 었습니다. 브레이크 포인트를 추가하면 예외가 발생한 곳을 바로 잡을 수 있고 예외 핸들러가 작동하지만 아이디어를 제공하기 때문에 예외 핸들러를 추가하는 것보다 낫습니다.
im8bit

21

이전보다 우아하지 않은 솔루션이 하나 더 있지만 예외 중단 점이나 핸들러를 추가하지 않은 경우 한 가지 방법 만 사용할 수 있습니다.
응용 프로그램이 충돌하고 원시 첫 스로우 콜 스택 (16 진수) 을 얻으면 Xcode 콘솔에 입력하십시오 info line *hex(별표와 0x16 진수 지정자를 잊지 마십시오 ).

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

lldb 를 사용하는 경우 다음 을 입력 할 수 있습니다image lookup -a hex (이 상황에서 별표없이) 하면 비슷한 결과를 얻을 수 있습니다.

이 방법을 사용하면 던지기 스택의 상단 (약 5-7 개의 시스템 예외 전파자가 있음)에서 충돌을 일으킨 함수로 이동하여 정확한 파일과 코드 줄을 결정할 수 있습니다.

또한 비슷한 효과를 얻으려면 터미널에서 atos 유틸리티를 사용할 수 있습니다.

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

그리고 기호화 된 스택 추적을 얻습니다 (적어도 디버그 기호가있는 함수의 경우). 이 방법은 각 주소 호출마다 필요하지 않기 때문에 info line콘솔 출력에서 ​​주소를 복사하여 터미널에 붙여 넣기 때문에 더 바람직 합니다.


9

예외 중단 점을 추가하고 (브레이크 포인트 탐색기 맨 아래에있는 + 사용) 조치 bt추가 할 수 있습니다 (조치 추가 단추를 클릭하고 디버거 명령을 선택한 후 텍스트 필드에 "bt"를 입력하십시오). 예외가 발생하자마자 스택 추적이 표시됩니다.


6

이것은 4.2에서 스택 추적을 얻지 못하는 일반적인 문제입니다. LLDB와 GDB를 서로 바꿔서 더 나은 결과를 얻을 수 있는지 확인할 수 있습니다.

여기에 버그 리포트를 제출하십시오.

http://developer.apple.com/bugreporter/

편집하다:

LLVM GCC 4.2로 다시 전환하면 이것이 발생하지 않을 것이라고 생각합니다. 그래도 필요한 기능을 잃을 수 있습니다.


예, 컴파일러 전환을 시도했지만 문제가 남아 있습니다. 그러나 어쨌든 감사합니다 :)
cekisakurek

그는 컴파일러가 아닌 스위칭 디버거를 제안했습니다.
bames53

1
참고 :이 경우 사용중인 컴파일러 또는 디버거 버전과는 아무 관련이 없습니다. 이것은 iOS의 콘솔 출력 변경입니다.
clarkcox3

이것의 경험이 얼마나 많은지 흥미 롭습니다. 몇 가지 문제가 있다고 생각합니다. 예외 중단 점에서 디버거를 중지시킬 수 없었습니다. GDB에서 LLDB로 전환하면 문제가 해결되었습니다.
Matt

6

주요 기능에서이 코드를 사용하십시오.

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int retVal;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException *exception) {
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    }
    @finally {
        [pool release];
    }
    return retVal;
}

스토리 보드에서는 작동하지 않는 것 같습니다. 2012-06-04 20 : 34 : 52.211 문제 [1944 : 207] 응용 프로그램 대리자가 기본 스토리 보드 파일을 사용하려면 창 속성을 구현해야합니다. 2012-06-04 20 : 34 : 52.213 문제 [1944 : 207] 응용 프로그램 실행이 끝날 때 응용 프로그램에 루트 뷰 컨트롤러가있을 것으로 예상됩니다
macasas

6

Xcode의 디버그 콘솔 프롬프트에서 다음을 입력하십시오.

image lookup -a 0x1234

그리고 그것은 당신에게 다음과 같은 것을 보여줄 것입니다 :

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202

고마워, 나는 이것을 정말로 찾고 있었다. 놀랍게도 전체 "처음 던지기 호출 스택"을 호출 스택으로 표시하는 지름길은 없습니다. 파이썬 lldb 스크립트를 쉽게 작성할 수있을 것 같습니다.
Ilya

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