3

如何在 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。没有很好的记录。我试图设置一个处理程序。它编译并运行,但没有发现段错误。

4

1 回答 1

3

您确定您没有获得 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
于 2009-03-05T13:57:31.217 回答