使用 Xcode 的所有异常断点时忽略某些异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14370632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 02:32:25  来源:igfitidea点击:

Ignore certain exceptions when using Xcode's All Exceptions breakpoint

iphoneiosxcode

提问by Phil Calvin

I have an All Exceptions breakpoint configured in Xcode:

我在 Xcode 中配置了一个 All Exceptions 断点:

screenshot of an exception breakpoint configured in Xcode breakpoint pain, configured to make a sound when an exception is thrown

Xcode断点痛中配置的异常断点截图,配置为抛出异常时发出声音

Sometimes Xcode will stop on a line like:

有时 Xcode 会停在如下一行:

[managedObjectContext save:&error];

with the following backtrace:

使用以下回溯:

backtrace showing NSPersistentStoreCoordinator throwing an exception inside the call to save:

回溯显示 NSPersistentStoreCoordinator 在调用保存时抛出异常:

but the program continues on as if nothing happened if you click Continue.

但是如果您单击继续,程序会继续运行,就好像什么也没发生一样。

How can I ignore these "normal" exceptions, but still have the debugger stop on exceptions in my own code?

如何忽略这些“正常”异常,但仍然让调试器在我自己的代码中停止异常?

(I understand that this happens because Core Data internally throws and catches exceptions, and that Xcode is simply honoring my request to pause the program whenever an exception is thrown. However, I want to ignore these so I can get back to debugging my own code!)

(我知道发生这种情况是因为 Core Data 在内部抛出并捕获异常,并且 Xcode 只是满足我在抛出异常时暂停程序的请求。但是,我想忽略这些,以便我可以回去调试我自己的代码!)

Moderators: this is similar to "Xcode 4 exception breakpoint filtering", but I think that question takes too long to get around to the point and doesn't have any useful answers. Can they be linked?

版主:这类似于“Xcode 4 异常断点过滤”,但我认为这个问题需要很长时间才能解决问题并且没有任何有用的答案。他们可以联系起来吗?

采纳答案by chendo

I wrote an lldb script that lets you selectively ignore Objective-C exceptions with a much simpler syntax, and it handles both OS X, iOS Simulator, and both 32bit and 64bit ARM.

我编写了一个 lldb 脚本,让您可以使用更简单的语法有选择地忽略 Objective-C 异常,它可以处理 OS X、iOS 模拟器以及 32 位和 64 位 ARM。

Installation

安装

  1. Put this script in ~/Library/lldb/ignore_specified_objc_exceptions.pyor somewhere useful.
  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 *)##代码## {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. Add the following to ~/.lldbinit:

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

    replacing ~/Library/lldb/ignore_specified_objc_exceptions.pywith the correct path if you saved it somewhere else.

  1. 将以下内容添加到~/.lldbinit

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

    ~/Library/lldb/ignore_specified_objc_exceptions.py如果您将其保存在其他地方,则替换为正确的路径。

Usage

用法

  • In Xcode, add a breakpoint to catch all Objective-Cexceptions
  • Edit the breakpoint and add a Debugger Command with the following command: ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
  • This will ignore exceptions where NSException-namematches NSAccessibilityExceptionOR -classNamematches NSSomeException
  • 在 Xcode 中,添加断点以捕获所有Objective-C异常
  • 编辑断点并使用以下命令添加调试器命令: ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
  • 这将忽略NSException-name匹配NSAccessibilityException-className匹配的异常NSSomeException

It should look something like this:

它应该是这样的:

Screenshot showing a breakpoint set in Xcode per the instructions

显示按照说明在 Xcode 中设置的断点的屏幕截图

In your case, you would use ignore_specified_objc_exceptions className:_NSCoreData

在你的情况下,你会使用 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.

有关脚本和更多详细信息,请参阅http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/

回答by Blake Watters

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

对于核心数据异常,我通常做的是从 Xcode 中删除“所有异常”断点,而是:

  1. Add a Symbolic Breakpoint on objc_exception_throw
  2. Set a Condition on the Breakpoint to (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])
  1. 在上添加符号断点 objc_exception_throw
  2. 在断点上设置条件为 (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])

The configured breakpoint should look something like this: Configuring the Breakpoint

配置的断点应如下所示: 配置断点

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 tablefor reference.

这将忽略_NSCoreData用于控制流的任何私有 Core Data 异常(由以 为前缀的类名确定)。请注意,适当的寄存器将取决于您正在运行的目标设备/模拟器。请查看此表以供参考。

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.

请注意,此技术可以轻松适应其他条件。棘手的部分是制作 BOOL 和 NSException 强制转换以使 lldb 对这种情况感到满意。

回答by james_alvarez

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:

这是当您有一段代码时的替代快速答案,例如第 3 部分库会引发您想要忽略的多个异常:

  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:
  1. 设置两个断点,一个在要忽略的异常抛出代码块之前和一个之后。
  2. 运行程序,直到它在异常处停止,然后在调试器控制台中键入“断点列表”,并找到“所有异常”断点的编号,它应该如下所示:

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

2:名称 = {'objc_exception_throw','__cxa_throw'},位置 = 2 选项:禁用 2.1:where = libobjc.A.dylib objc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0 2.2: where = libc++abi.dylib__cxa_throw,地址 = 0x00007fff8d19fab7,未解析,命中数 = 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'.

  1. 这意味着它是断点 2。现在在 xcode 中,编辑第一个断点(在异常抛出代码之前)并将操作更改为“调试器命令”并键入“断点禁用 2”(并设置“自动继续...”复选框)。

  2. 对违规行之后的断点执行相同的操作,并使用命令“断点启用 2”。

The all breakpoints exception will now turn on and off so it's only active when you need it.

所有断点异常现在将打开和关闭,因此它仅在您需要时才处于活动状态。