Development Tip

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

yourdevel 2020. 10. 16. 08:11
반응형

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


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

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

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

[managedObjectContext save:&error];

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

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

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

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

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

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


훨씬 간단한 구문으로 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
  • This will ignore exceptions where NSException -name matches NSAccessibilityException OR -className matches NSSomeException

It should look something like this:

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

In your case, you would use ignore_specified_objc_exceptions className:_NSCoreData

See http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/ for the script and more details.


For Core Data exceptions, what I typically do is remove the "All Exceptions" breakpoint from Xcode and instead:

  1. Add a Symbolic Breakpoint on objc_exception_throw
  2. Set a Condition on the Breakpoint to (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])

The configured breakpoint should look something like this: 중단 점 구성

This will ignore any private Core Data exceptions (as determined by the class name being prefixed by _NSCoreData) that are used for control flow. Note that the appropriate register is going to be dependent on the target device / simulator that you are running in. Take a look at this table for reference.

Note that this technique can be adapted easily to other conditionals. The tricky part was in crafting the BOOL and NSException casts to get lldb happy with the condition.


Here is an alternative quick answer for when you have a block of code e.g. a 3rd part library that throws multiple exceptions that you want to ignore:

  1. Set two breakpoints, one before and one after the exception throwing block of code you want to ignore.
  2. Run the program, until it stops at an exception, and type 'breakpoint list' into the debugger console, and find the number of the 'all exceptions' break point, it should look like this:

2: names = {'objc_exception_throw', '__cxa_throw'}, locations = 2 Options: disabled 2.1: where = libobjc.A.dylibobjc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0 2.2: where = libc++abi.dylib__cxa_throw, address = 0x00007fff8d19fab7, unresolved, hit count = 0

  1. This means it is breakpoint 2. Now in xcode, edit the first breakpoint (before the exception throwing code) and change the action to 'debugger command' and type in 'breakpoint disable 2' (and set 'automatically continue...' checkbox ).

  2. Do the same for the break point after the offending line and have the command 'breakpoint enable 2'.

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

참고 URL : https://stackoverflow.com/questions/14370632/ignore-certain-exceptions-when-using-xcodes-all-exceptions-breakpoint

반응형