OSX中Carbon C应用程序的异常包装器
-
03-07-2019 - |
题
如何在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 ++异常是否会捕获段错误。我的应用程序目前是C.我可以尝试使用包装器和#ifdef来使它成为C ++但是这对应用程序来说是很多工作,我不认为C ++异常会抓住崩溃。
2)signal + setjump + longjmp。我认为这样可行......这就是它的设计目标。但是我设置了我的SEGV错误处理程序[事实上我为每个信号设置了它!]并且它在崩溃期间从未被调用过。我可以在调用raise(SEGV)时手动测试(并成功)。但崩溃似乎并没有真正称之为崩溃。我的想法是CFM应用程序无法访问完整的BSD信号,只能访问子集,并且Mach应用程序对于Real Thing是必需的。
3)MPSetExceptionHandler。没有详细记录。我试图设置一个处理程序。它编译并运行,但没有发现段错误。
解决方案
你确定你没有获得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