Xcode의 모든 예외 중단 점을 사용할 때 특정 예외를 무시합니다.


78

Xcode에 구성된 모든 예외 중단 점이 있습니다.

Xcode 중단 점 통증에 구성된 예외 중단 점의 스크린 샷, 예외가 throw 될 때 소리를 내도록 구성됨

때때로 Xcode는 다음과 같은 줄에서 중지됩니다.

[managedObjectContext save:&error];

다음 역 추적을 사용합니다.

저장 호출 내에서 예외를 발생시키는 NSPersistentStoreCoordinator를 보여주는 역 추적 :

그러나 계속을 클릭하면 아무 일도 일어나지 않는 것처럼 프로그램이 계속됩니다.

이러한 "정상적인"예외를 무시하지만 여전히 내 코드의 예외에서 디버거가 중지되도록하려면 어떻게해야합니까?

(Core Data가 내부적으로 예외를 발생시키고 포착하기 때문에 이런 일이 발생한다는 것을 알고 있으며 Xcode는 예외가 발생할 때마다 프로그램을 일시 중지하라는 내 요청을 존중하는 것뿐입니다. 그러나이를 무시하고 내 코드 디버깅으로 돌아갈 수 있습니다. !)

중재자 : 이것은 "Xcode 4 예외 중단 점 필터링" 과 비슷하지만이 질문은 요점을 파악하는 데 너무 오래 걸리고 유용한 답변이 없다고 생각합니다. 연결할 수 있습니까?


"특정 예외"에 대해 더 명확히 할 수 있습니까?
Jesse Rusak 2013 년

아, 죄송합니다! 준비되기 전에 Stack Overflow가 게시되었습니다 (실수로 태그 필드에 Enter 키를 누르십시오.) 편집하겠습니다. = (
Phil Calvin

이것은 다른 질문과 똑같은 질문처럼 보입니다. 닫고 다른쪽에 현상금걸면 어떨까요? 명확하지 않다고 생각되면 다른 항목에 수정을 제안하여 정리할 수도 있습니다.
Jesse Rusak 2013 년

답변:


41

훨씬 간단한 구문으로 Objective-C 예외를 선택적으로 무시할 수있는 lldb 스크립트를 작성했으며 OS X, iOS 시뮬레이터, 32 비트 및 64 비트 ARM을 모두 처리합니다.

설치

  1. 이 스크립트를 ~/Library/lldb/ignore_specified_objc_exceptions.py또는 유용한 곳에 두십시오 .
import lldb
import re
import shlex

# This script allows Xcode to selectively ignore Obj-C exceptions
# based on any selector on the NSException instance

def getRegister(target):
    if target.triple.startswith('x86_64'):
        return "rdi"
    elif target.triple.startswith('i386'):
        return "eax"
    elif target.triple.startswith('arm64'):
        return "x0"
    else:
        return "r0"

def callMethodOnException(frame, register, method):
    return frame.EvaluateExpression("(NSString *)[(NSException *)${0} {1}]".format(register, method)).GetObjectDescription()

def filterException(debugger, user_input, result, unused):
    target = debugger.GetSelectedTarget()
    frame = target.GetProcess().GetSelectedThread().GetFrameAtIndex(0)

    if frame.symbol.name != 'objc_exception_throw':
        # We can't handle anything except objc_exception_throw
        return None

    filters = shlex.split(user_input)

    register = getRegister(target)


    for filter in filters:
        method, regexp_str = filter.split(":", 1)
        value = callMethodOnException(frame, register, method)

        if value is None:
            output = "Unable to grab exception from register {0} with method {1}; skipping...".format(register, method)
            result.PutCString(output)
            result.flush()
            continue

        regexp = re.compile(regexp_str)

        if regexp.match(value):
            output = "Skipping exception because exception's {0} ({1}) matches {2}".format(method, value, regexp_str)
            result.PutCString(output)
            result.flush()

            # If we tell the debugger to continue before this script finishes,
            # Xcode gets into a weird state where it won't refuse to quit LLDB,
            # so we set async so the script terminates and hands control back to Xcode
            debugger.SetAsync(True)
            debugger.HandleCommand("continue")
            return None

    return None

def __lldb_init_module(debugger, unused):
    debugger.HandleCommand('command script add --function ignore_specified_objc_exceptions.filterException ignore_specified_objc_exceptions')
  1. 다음에 다음을 추가하십시오 ~/.lldbinit.

    command script import ~/Library/lldb/ignore_specified_objc_exceptions.py

    ~/Library/lldb/ignore_specified_objc_exceptions.py다른 곳에 저장 한 경우 올바른 경로로 바꿉니다 .

용법

  • Xcode에서 모든 Objective-C 예외 를 포착하는 중단 점을 추가합니다.
  • 중단 점을 편집하고 다음 명령을 사용하여 디버거 명령을 추가합니다. ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
  • 이것은 NSException -name일치 NSAccessibilityException또는 -className일치 하는 예외를 무시합니다.NSSomeException

다음과 같이 보일 것입니다.

지침에 따라 Xcode에 설정된 중단 점을 보여주는 스크린 샷

귀하의 경우에는 ignore_specified_objc_exceptions className:_NSCoreData

스크립트 및 자세한 내용 은 http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/ 를 참조 하십시오.


이것은 나를 위해 정말 잘 작동합니다. 스크립트 및 설치 지침을 Stack Overflow에 직접 기꺼이 제공 하시겠습니까 (따라서 cc-wiki 로 라이선스를 부여 하시겠습니까?). 그렇다면이 답변을 수락하겠습니다!
Phil Calvin

마지막 응답에서 @chendo 태그를 지정해야했습니다.
Phil Calvin

@PhilCalvin MIT로 라이센스하는 것이 더 좋을까요?
chendo

1
잘 작동합니다. 다시 스트레스를 받으려면 여기에 C ++ 예외도 발생하므로 중단 점을 "Objective-C"로 설정해야합니다.
Matej Bukovinski 2014 년

1
Xcode 5.1에서 정말 잘 작동합니다. 중요한 세부 사항 : 당신 선택하는 오브젝티브 C 예외 유형으로 (지침에서 언급 한 바와 같이합니다.)
필 캘빈

87

핵심 데이터 예외의 경우 일반적으로 Xcode에서 "모든 예외"중단 점을 제거하고 대신 다음을 수행합니다.

  1. 에 기호 중단 점 추가 objc_exception_throw
  2. 중단 점의 조건을 다음으로 설정합니다. (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])

구성된 중단 점은 다음과 같습니다. 중단 점 구성

이는 _NSCoreData제어 흐름에 사용되는 모든 비공개 Core Data 예외 (접두사가 붙은 클래스 이름에 의해 결정됨)를 무시합니다 . 적절한 레지스터는 실행중인 대상 장치 / 시뮬레이터에 따라 다릅니다. 이 표 를 참조하십시오.

이 기술은 다른 조건에 쉽게 적용 할 수 있습니다. 까다로운 부분은 BOOL 및 NSException 캐스트를 작성하여 lldb가 조건에 만족하도록 만드는 것이 었습니다.


특히 여러 스레드에서 Core Data를 사용할 때 매우 유용하며 이러한 잘못된 예외가 훨씬 더 자주 발생합니다! 대단히 감사합니다!
bmasters apr

1
나는 장치에서 이것을 시도하고있다 $r0: (BOOL)(! (BOOL)[[(NSException *)$r0 className] hasPrefix:@”_NSCoreData”]). 그래도 작동하지 않습니다. 콘솔에서 다음을 얻습니다. Stopped due to an error evaluating condition of breakpoint 1.1: "(BOOL)(! (BOOL)[[(NSException *)$r0 className] hasPrefix:@‚Äù_NSCoreData‚Äù])" error: unexpected '@' in program error: 1 errors parsing expression
lammert

@lammert 예제에서 복사 한 따옴표를 실제 따옴표로 바꾸고 싶을 수 있습니다. 복사 한 내용에는 미리 따옴표가 포함되어 있습니다.
제레미 푸

방금 Xcode 4.6.3 (4H1503)에서 시도했지만 currentName선택기가 마음에 들지 않았습니다 . [(NSException *)$eax name]나를 위해 일 하도록 변경했습니다 .
Adam Sharp

4
iPhone6에서 iOS 8.2가 설치된 Xcode 6.2에서는를로 변경해야 $r0했습니다 $x0(여기에 정의 된대로 : sealiesoftware.com/blog/archive/2013/09/12/… ). 따라서 조건은 다음과 같습니다.(BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])
Wim Fikkert 2015 년

16

다음은 무시할 여러 예외를 발생시키는 세 번째 부분 라이브러리와 같은 코드 블록이있는 경우에 대한 대안적인 빠른 답변입니다.

  1. 두 개의 중단 점을 설정하십시오. 하나는 무시할 예외를 던지는 코드 블록 앞과 뒤에 있습니다.
  2. 예외에서 멈출 때까지 프로그램을 실행하고 디버거 콘솔에 '중단 점 목록'을 입력하고 '모든 예외'중단 점의 수를 찾으면 다음과 같아야합니다.

2 : 이름 = { 'objc_exception_throw', '__cxa_throw'}, 위치 = 2 옵션 : 비활성화 됨 2.1 : 여기서 = libobjc.A.dylib objc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0 2.2: where = libc++abi.dylib__cxa_throw, 주소 = 0x00007fff8d19fab7, 미해결, 적중 횟수 = 0

  1. 즉, 중단 점 2입니다. 이제 xcode에서 첫 번째 중단 점 (예외 발생 코드 이전)을 편집하고 작업을 '디버거 명령'으로 변경하고 '중단 점 비활성화 2'를 입력하고 '자동으로 계속 ...'확인란을 설정합니다. ).

  2. 문제가되는 줄 뒤의 중단 점에 대해 동일한 작업을 수행하고 'breakpoint enable 2'명령을 사용합니다.

이제 모든 중단 점 예외가 켜지고 꺼 지므로 필요할 때만 활성화됩니다.


고마워! 정확히 내가 찾던 것. 예외 ID를 찾을 수 없었지만 강제로 강제했습니다. 그 부분을 더 자세히 설명 할 수 있습니까? 중단 점 ID / 위치를 보려면 해당 '중단 점 목록'을 붙여 넣을 Xcode에서 정확히 어디에 있습니까?
vir us

놀랄 만한! 매력처럼 작동합니다!
Sergey Grischyov

1
우수-이 솔루션은 다른 답변보다 훨씬 간단하며 완벽하게 작동합니다.
ajgryc

훌륭한! 이것은 SO 답변의 보석이며 받아 들여야합니다.
jb 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.