OK, stellen Sie sich vor, mein Haltepunkt in objc_exception_throw
wurde gerade ausgelöst. Ich sitze an der Debugger-Eingabeaufforderung und möchte weitere Informationen zum Ausnahmeobjekt erhalten. Wo finde ich es?
OK, stellen Sie sich vor, mein Haltepunkt in objc_exception_throw
wurde gerade ausgelöst. Ich sitze an der Debugger-Eingabeaufforderung und möchte weitere Informationen zum Ausnahmeobjekt erhalten. Wo finde ich es?
Antworten:
Das Ausnahmeobjekt wird als erstes Argument an übergeben objc_exception_throw
. LLDB bietet $arg1
.. $argn
Variablen, die auf Argumente in der richtigen Aufrufkonvention verweisen, wodurch das Drucken der Ausnahmedetails vereinfacht wird:
(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
Stellen Sie sicher, dass Sie den objc_exception_throw
Frame im Aufrufstapel auswählen , bevor Sie diese Befehle ausführen. Weitere Informationen zum Ausführen auf der Bühne finden Sie unter "Erweitertes Debugging und Adressbereinigung" in den WWDC15-Sitzungsvideos.
Veraltete Informationen
Wenn Sie GDB verwenden, hängt die Syntax für das erste Argument von den Aufrufkonventionen der Architektur ab, auf der Sie ausgeführt werden. Wenn Sie auf einem tatsächlichen iOS-Gerät debuggen, befindet sich der Zeiger auf das Objekt im Register r0
. Verwenden Sie die folgende einfache Syntax, um es zu drucken oder Nachrichten an es zu senden:
(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]
Auf dem iPhone Simulator werden alle Funktionsargumente auf dem Stapel übergeben, sodass die Syntax erheblich schrecklicher ist. Der kürzeste Ausdruck, den ich konstruieren könnte, ist *(id *)($ebp + 8)
. Um die Schmerzen zu lindern, schlage ich vor, eine Convenience-Variable zu verwenden:
(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]
Sie können auch $exception
automatisch festlegen , wann immer der Haltepunkt ausgelöst wird, indem Sie dem Haltepunkt eine Befehlsliste hinzufügen objc_exception_throw
.
(Beachten Sie, dass in allen von mir getesteten Fällen das Ausnahmeobjekt zum Zeitpunkt des Haltepunkttreffens auch in den Registern eax
und vorhanden war edx
. Ich bin mir jedoch nicht sicher, ob dies immer der Fall sein wird.)
Hinzugefügt von Kommentar unten:
Wählen Sie in lldb den Stapelrahmen für aus objc_exception_throw
und geben Sie den folgenden Befehl ein:
(lldb) po *(id *)($esp + 4)
objc_exception_throw
in der LLDB weiterbringe : po *(id *)($esp + 4)
.
objc_exception_throw
).
po $eax
funktioniert für mich im simulator als anhänger an das $r0
wenn auf gerät.
auf neuen Simulatoren (iOS 8, 64bit) xcode 6 verwende ich im Ausnahmerahmen: objc_exception_throw
po $rax
in 32bit:
po $eax
Was ist Rax?
Rax ist ein 64-Bit-Register, das das alte eax ersetzt
Wie finde ich alle Register?
register read
Zum Zeitpunkt dieses Schreibens ist dieser Beitrag mein Top-Google-Hit für: lldb print exception . Daher füge ich diese Antwort hinzu, um lldb und x86_64 zu berücksichtigen.
Meine Versuche, die Ausnahme mit zu finden, sind mit po $eax
fehlgeschlagen error: Couldn't materialize struct: Couldn't read eax (materialize)
. Andere Versuche, die in verknüpften Dokumenten aus früheren Antworten beschrieben wurden, schlugen ebenfalls fehl.
Der Schlüssel war, dass ich zuerst auf den objc_exception_throw
Rahmen in meinem Haupt-Thread klicken musste . lldb startet nicht in diesem Frame.
In all meinen Such- und folgenden Beispielen war dieser Blogeintrag der erste, der Dinge auf eine Weise erklärte, die für mich funktionierte. Es ist moderner und wird im August 2012 veröffentlicht.
Wenn Sie eine catch-Anweisung haben, fügen Sie dort einen Haltepunkt ein, und Sie können das Ausnahmeobjekt an diesem Punkt überprüfen.
Wenn Sie keine catch-Anweisung haben, fahren Sie fort.
In Ihrem Terminal wird folgende Nachricht angezeigt:
Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInvalidArgumentException', Grund: ' * - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: Versuch, kein Objekt aus Objekten einzufügen [0]'
Sie suchen jedoch wahrscheinlich nach einer Möglichkeit, es zu überprüfen, ohne fortzufahren, da Sie Ihre schöne Stapelverfolgung verlieren, wenn die Anwendung beendet wird.
Dafür klingt es so, als wäre Fnords Antwort die beste, aber ich konnte sie in LLDB nicht zum Laufen bringen.