Macos 在64位OS X应用程序中处理马赫数异常

Macos 在64位OS X应用程序中处理马赫数异常,macos,osx-snow-leopard,darwin,Macos,Osx Snow Leopard,Darwin,我已经能够注册我自己的马赫端口来捕获我的应用程序中的马赫异常,当我以32位为目标时,它工作得很好。但是,当我以64位为目标时,会调用我的异常处理程序catch\u exception\u raise(),但传递给处理程序的异常代码数组是32位宽的。这在32位构建中是预期的,但在64位构建中不是 在我捕获EXC_BAD_ACCESS的情况下,第一个代码是错误号,第二个代码应该是故障地址。由于第二个代码为32位宽,因此64位故障地址的高32位被截断 我在中找到了一个标记,我可以传入任务设置异常异常异

我已经能够注册我自己的马赫端口来捕获我的应用程序中的马赫异常,当我以32位为目标时,它工作得很好。但是,当我以64位为目标时,会调用我的异常处理程序
catch\u exception\u raise()
,但传递给处理程序的异常代码数组是32位宽的。这在32位构建中是预期的,但在64位构建中不是

在我捕获
EXC_BAD_ACCESS
的情况下,第一个代码是错误号,第二个代码应该是故障地址。由于第二个代码为32位宽,因此64位故障地址的高32位被截断

我在
中找到了一个标记,我可以传入
任务设置异常异常异常端口()
名为
马赫异常异常异常异常异常异常异常异常代码
,通过查看达尔文源代码,它似乎可以控制传递给处理程序的代码的大小。看起来它应该与传递到
task\u set\u exception\u ports()
的行为一起进行OR

然而,当我这样做并触发异常时,我的mach端口会收到通知,我调用
exc_server()
,但我的处理程序从未被调用,当回复消息发送回内核时,我会得到默认的异常行为

我的目标是10.6SDK


我真希望苹果能更好地记录这些东西。有人有什么想法吗?

嗯,我想出来了

要处理马赫数异常,必须为感兴趣的异常注册一个马赫数端口。然后等待消息到达另一个线程的端口。当消息到达时,您调用
exc\u server()
,其实现由System.library提供
exec_server()
接收到达的消息并调用您必须提供的三个处理程序之一
catch\u exception\u raise()
catch\u exception\u raise\u state()
,或
catch\u exception\u raise\u state\u identity()
,具体取决于传递给
task\u set\u exception\u port()的参数。32位应用程序就是这样做的

对于64位应用程序,32位方法仍然有效,但在处理程序中传递给您的数据可能会被截断为32位。要将64位数据传递给您的处理程序,需要做一些额外的工作,这不是很简单,而且据我所知,没有很好的文档记录。通过查看GDB的源代码,我偶然发现了解决方案

当消息到达端口时,您必须调用
mach\u exc\u server()
,而不是调用
exc\u server()
。处理程序还必须具有不同的名称
catch\u mach\u exception\u raise()
catch\u exception\u raise\u state()
,以及
catch\u mach\u exception\u raise\u state\u identity()
。处理程序的参数与32位对应的参数相同。 问题是
mach\u exc\u server()
没有像
exc\u server()
那样为您提供。要实现
mach_exc_server()
需要使用MIG(mach接口生成器)实用程序。MIG获取一个接口定义文件并生成一组源文件,其中包括一个服务器功能,该功能将mach消息发送给您提供的处理程序。10.5和10.6 SDK包括一个用于异常消息的MIG定义文件,并将生成
mach_exc_server()
功能。然后将生成的源文件包括在项目中,就可以开始了

很好的一点是,如果您的目标是10.6+(可能是10.5),那么您可以对32位和64位使用相同的异常处理。设置异常端口时,仅使用
MACH\u exception\u code
设置异常行为。异常代码将作为64位值通过,但您可以在32位构建中将其截断为32位

我把
mach_exc.defs
文件复制到我的源目录,打开一个终端,使用命令
mig-v mach_exc.defs
。这生成了
mach_exc.h
mach_excServer.c
mach_excUser.c
。然后,我将这些文件包括在我的项目中,在源文件中为服务器函数添加了正确的声明,并实现了我的处理程序。然后我构建了我的应用程序,很好地运行


嗯,这不是最好的描述,但希望它能帮助其他人。

我想知道这是否与您正在运行的内核有关;在32位内核下会出现32位异常,在64位内核下会出现64位异常?在10.6上,32位内核仍然是默认的,但是如果你有足够多的新Mac,你可以试试……32位内核完全支持64位,并且会将64位或32位异常传递给应用程序。这一切都取决于你的应用程序如何请求和处理它们。谢谢,这是我能找到的关于此的唯一文档。当你处理原始异常时,你是否需要以某种方式向原始线程发送信号,以便它继续?看起来好像被困在等待中了。干杯,布拉德,我也遇到了同样的问题,这就解决了。相关的GDB代码供任何感兴趣的人使用。@hooleyhoop您需要从异常处理程序返回
KERN\u SUCCESS
(例如
catch\u mach\u exception\u raise()
),然后使用
mach\u exc\u server()为您设置的消息缓冲区返回异常端口。如果要在继续执行线程之前修改计算机寄存器或其他任何内容,可以在异常处理程序中执行,也可以在向异常端口发回消息之前挂起线程(
thread\u suspend()
),然后在进行修改后恢复。实际的代码片段会很好,我花了两天时间试图找出如何捕获
EXC\u BAD\u ACCESS
并打印堆栈跟踪。到目前为止运气不好。