OSX 中 Carbon C 应用程序的异常包装器
Posted
技术标签:
【中文标题】OSX 中 Carbon C 应用程序的异常包装器【英文标题】:Exception wrapper for Carbon C app in OSX 【发布时间】:2010-10-11 12:17:09 【问题描述】:如何在 OSX Carbon 应用程序中有效地捕获和处理来自 C 的分段错误?
背景:我正在制作一个 OSX Carbon 应用程序。我必须从第三方调用库函数。由于线程问题,该函数偶尔会崩溃,通常是因为它从一个线程更新自身,并且当我从另一个线程查询它时,它有一些内部过时的指针或句柄。该功能对我来说是一个黑匣子。我希望能够调用该函数,但能够“捕获”它是否崩溃并提供替代返回。 在 Windows 中,我可以使用简单的 Visual C 和 Intel C 编译器的 __try 和 __except。
/* Working Windows Example */
__try x=DangerousFunction(y);
__except(EXCEPTION_EXECUTE_HANDLER) x=0.0; /* whups, func crashed! */
我正在尝试为 OSX 制作相同类型的崩溃捕捉器。我在一个非常大的应用程序上使用纯 C。我每秒调用该函数数百万次,因此效率也非常重要。 (令人印象深刻的是,Windows __try() 开销非常小!)
这是我尝试过的:
1) C++ 异常。我不确定 C++ 异常是否会捕获 segfault 崩溃。我的应用目前是 C。我可以尝试使用包装器和#ifdefs 使其成为 C++,但这对应用来说是很多工作,而且我认为 C++ 异常不会导致崩溃。
2) 信号 + setjump + longjmp。我认为这会起作用......这就是它的设计目的。但是我设置了我的 SEGV 错误处理程序 [实际上我为每个信号都设置了它!] 并且在崩溃期间它从未被调用过。我可以在调用 raise(SEGV) 时手动测试(并成功)。但崩溃似乎并没有真正调用它。我的想法是 CFM 应用程序无法访问完整的 BSD 信号,只有一个子集,并且 Mach 应用程序对于 Real Thing 是必需的。
3) MPSetExceptionHandler。没有很好的记录。我试图设置一个处理程序。它编译并运行,但没有捕获段错误。
【问题讨论】:
【参考方案1】:你确定你得到的不是 SIGBUS,而是 SIGSEGV?
以下捕获 SIGBUS 是由于尝试在内存位置 0 写入引起的:
cristi:tmp diciu$ cat test.c
#include <signal.h>
static void sigac(int sig)
printf("sig action here, signal is %d\n", sig);
exit(1);
int main()
(void)signal(SIGSEGV, sigac);
(void)signal(SIGBUS, sigac);
printf("Raising\n");
strcpy(0, "aaksdjkajskd|");
cristi:tmp diciu$ ./a.out
Raising
sig action here, signal is 10
【讨论】:
是的。我认为关键是要捕获每种类型的每个异常!以上是关于OSX 中 Carbon C 应用程序的异常包装器的主要内容,如果未能解决你的问题,请参考以下文章
OSX 10.9 Mavericks 钥匙串 API 坏了?