Nun, ich habe es herausgefunden.
Um Mach-Ausnahmen zu behandeln, müssen Sie einen Mach-Port für die Ausnahmen registrieren, die Sie interessieren. Sie warten dann auf eine Nachricht, die auf dem Port in einem anderen Thread ankommt. Wenn eine Nachricht eintrifft, rufen Sie exc_server()
an, deren Implementierung von System.library bereitgestellt wird. exec_server()
übernimmt die Nachricht, die angekommen ist, und ruft einen von drei Handlern auf, die Sie angeben müssen. catch_exception_raise()
, catch_exception_raise_state()
oder catch_exception_raise_state_identity()
abhängig von den Argumenten, die Sie an task_set_exception_ports()
übergeben haben. So wird es für 32-Bit-Apps gemacht.
Für 64-Bit-Anwendungen funktioniert die 32-Bit-Methode immer noch, aber die Daten, die Sie in Ihrem Handler übergeben, werden möglicherweise auf 32 Bit gekürzt. Um 64-Bit-Daten zu erhalten, die an Ihre Handler übergeben werden, ist ein wenig zusätzlicher Aufwand erforderlich, der nicht sehr geradlinig ist und, soweit ich es beurteilen kann, nicht sehr gut dokumentiert ist. Ich stolperte über die Lösung, indem ich mir die Quellen für GDB anschaute.
Anstatt exc_server()
anzurufen, wenn eine Nachricht am Port ankommt, müssen Sie stattdessen mach_exc_server()
anrufen. Die Handler müssen auch andere Namen haben: catch_mach_exception_raise()
, catch_mach_exception_raise_state()
und catch_mach_exception_raise_state_identity()
. Die Parameter für die Handler sind die gleichen wie ihre 32-Bit-Gegenstücke. Das Problem ist, dass mach_exc_server()
nicht für Sie zur Verfügung gestellt wird, wie exc_server()
ist. Um die Implementierung für mach_exc_server()
zu erhalten, muss das Dienstprogramm MIG (Mach Interface Generator) verwendet werden. MIG verwendet eine Schnittstellendefinitionsdatei und generiert eine Reihe von Quelldateien, die eine Serverfunktion enthalten, die mach-Meldungen an von Ihnen bereitgestellte Handler ausgibt. Die SDKs 10.5 und 10.6 enthalten eine MIG-Definitionsdatei <mach_exc.defs> für die Ausnahmebedingungsnachrichten und generieren die mach_exc_server()
-Funktion. Sie fügen dann die generierten Quelldateien in Ihr Projekt ein und dann können Sie loslegen.
Das nette Ding ist, dass, wenn Sie 10.6+ (und vielleicht 10.5) zielen, Sie die gleiche Ausnahmebehandlung für 32 und 64 Bit verwenden können. Just OR das Ausnahmeverhalten mit MACH_EXCEPTION_CODES
, wenn Sie Ihre Ausnahme-Ports festlegen.Die Ausnahmecodes werden als 64-Bit-Werte ausgegeben, Sie können sie jedoch in Ihrem 32-Bit-Build auf 32 Bit abschneiden.
Ich nahm die mach_exc.defs
Datei und kopierte es in mein Quellverzeichnis, öffnete ein Terminal und verwendete den Befehl mig -v mach_exc.defs
. Dies erzeugte mach_exc.h
, mach_excServer.c
und mach_excUser.c
. Ich habe dann diese Dateien in mein Projekt eingefügt, die korrekte Deklaration für die Serverfunktion in meiner Quelldatei hinzugefügt und meine Handler implementiert. Ich habe dann meine App gebaut und war gut zu gehen.
Nun, das ist nicht die beste Beschreibung, aber hoffentlich hilft es jemand anderen aus.
Ich frage mich, ob das mehr mit dem Kernel zu tun hat, den Sie gerade ausführen; Sie erhalten 32-Bit-Ausnahmen unter dem 32-Bit-Kernel und 64-Bit-Ausnahmen unter dem 64-Bit-Kernel? Der 32-Bit-Kernel ist immer noch der Standard auf 10.6, aber wenn Sie einen neuen genug Mac haben, können Sie es versuchen ... –
Der 32-Bit-Kernel ist vollständig 64-Bit-bewusst und wird entweder 64-Bit oder 32 übergeben -Bit Ausnahmen zu einer Anwendung. Es hängt alles davon ab, wie Ihre App danach fragt und sie behandelt. –