嗯,我想通了。
要处理马赫异常,您必须为您感兴趣的异常注册一个马赫端口。然后在另一个线程中等待消息到达该端口。当消息到达时,您调用exc_server()
由 System.library 提供的实现。exec_server()
获取到达的消息并调用您必须提供的三个处理程序之一。catch_exception_raise()
, catch_exception_raise_state()
, 或catch_exception_raise_state_identity()
取决于您传递给task_set_exception_ports()
. 这就是 32 位应用程序的处理方式。
对于 64 位应用程序,32 位方法仍然有效,但在处理程序中传递给您的数据可能会被截断为 32 位。要将 64 位数据传递给您的处理程序,需要一些额外的工作,这不是很直接,而且据我所知,没有很好的文档记录。通过查看 GDB 的源代码,我偶然发现了解决方案。
您不必exc_server()
在消息到达端口时调用,mach_exc_server()
而是必须调用。处理程序也必须具有不同的名称catch_mach_exception_raise()
,catch_mach_exception_raise_state()
, 和catch_mach_exception_raise_state_identity()
。处理程序的参数与它们的 32 位对应项相同。问题是mach_exc_server()
没有为您提供的方式exc_server()
是。要获得实现,mach_exc_server()
需要使用 MIG(Mach 接口生成器)实用程序。MIG 采用接口定义文件并生成一组源文件,其中包括一个服务器函数,该函数将 mach 消息分派给您提供的处理程序。10.5 和 10.6 SDK 包含一个用于异常消息的 MIG 定义文件 <mach_exc.defs> 并将生成mach_exc_server()
功能。然后,您将生成的源文件包含在您的项目中,然后您就可以开始了。
好消息是,如果您的目标是 10.6+(也许是 10.5),您可以对 32 位和 64 位使用相同的异常处理。MACH_EXCEPTION_CODES
设置异常端口时的异常行为。异常代码将以 64 位值的形式出现,但您可以在 32 位构建中将它们截断为 32 位。
我把mach_exc.defs
文件复制到我的源目录,打开一个终端并使用命令mig -v mach_exc.defs
。这产生mach_exc.h
,mach_excServer.c
和mach_excUser.c
。然后我将这些文件包含在我的项目中,在我的源文件中添加了服务器函数的正确声明并实现了我的处理程序。然后我构建了我的应用程序,一切顺利。
好吧,这不是最好的描述,但希望它可以帮助其他人。