80

Xcode で All Exceptions ブレークポイントを構成しています。

例外がスローされたときに音を出すように構成された、Xcode ブレークポイント ペインで構成された例外ブレークポイントのスクリーンショット

Xcode は次のような行で停止することがあります。

[managedObjectContext save:&error];

次のバックトレースを使用:

NSPersistentStoreCoordinator が save の呼び出し内で例外をスローしていることを示すバックトレース:

ただし、[続行] をクリックすると、プログラムは何も起こらなかったかのように続行します。

これらの「通常の」例外を無視するにはどうすればよいですか?ただし、自分のコードで例外が発生した場合にデバッガーを停止させるにはどうすればよいですか?

(これは、Core Data が内部的に例外をスローしてキャッチするために発生することと、例外がスローされるたびにプログラムを一時停止するという私の要求を Xcode が単に受け入れていることを理解しています。ただし、これらを無視して、自分のコードのデバッグに戻ることができるようにしたいと考えています。 !)

モデレーター: これは「Xcode 4 例外ブレークポイント フィルタリング」に似ていますが、その質問は要点を理解するのに時間がかかりすぎて、有用な回答がないと思います。それらはリンクできますか?

4

3 に答える 3

89

コア データの例外については、通常、Xcode から「すべての例外」ブレークポイントを削除し、代わりに次のようにします。

  1. にシンボリック ブレークポイントを追加するobjc_exception_throw
  2. ブレークポイントに条件を設定して(BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])

構成されたブレークポイントは次のようになります。 ブレークポイントの構成

_NSCoreDataこれにより、制御フローに使用されるプライベート Core Data 例外 (クラス名の前に. 適切なレジスタは、実行しているターゲット デバイス/シミュレータに依存することに注意してください。参照用にこの表を見てください。

この手法は、他の条件に簡単に適用できることに注意してください。トリッキーな部分は、BOOL および NSException キャストを作成して、lldb を条件に満足させることでした。

于 2013-01-17T03:17:28.323 に答える
42

私は lldb スクリプトを作成しました。このスクリプトは、より単純な構文で Objective-C の例外を選択的に無視できるようにし、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/を参照してください。

于 2013-10-09T02:52:47.813 に答える
17

無視したい複数の例外をスローする第 3 部分のライブラリなど、コード ブロックがある場合の別の簡単な回答を次に示します。

  1. 無視する例外をスローするコード ブロックの前後に 1 つずつ、2 つのブレークポイントを設定します。
  2. 例外で停止するまでプログラムを実行し、デバッガー コンソールに「ブレークポイント リスト」と入力して、「すべての例外」ブレーク ポイントの数を確認します。次のようになります。

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, address = 0x00007fff8d19fab7, unresolved, hit count = 0

  1. これは、ブレークポイント 2 であることを意味します。xcode で、最初のブレークポイント (例外をスローするコードの前) を編集し、アクションを「debugger command」に変更して、「breakpoint disable 2」と入力します (「automatically continue...」チェックボックスを設定します)。 )。

  2. 問題のある行の後のブレーク ポイントに対して同じことを行い、コマンド 'breakpoint enable 2' を実行します。

すべてのブレークポイントの例外はオンとオフを切り替えるようになり、必要な場合にのみアクティブになります。

于 2014-12-05T13:35:52.880 に答える