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です。ラッパーと#ifdefsを試してC ++にすることもできますが、これはアプリにとって多くの作業であり、C ++例外がクラッシュをキャッチするとは思いません。
2)シグナル+ setjump + longjmp。私はこれがうまくいくと思った...それはそれが設計されているものです。しかし、SEGVエラーハンドラーを設定し(実際、すべての信号に対して設定しました!)、クラッシュ中に呼び出されることはありません。 raise(SEGV)を呼び出すときに、手動でテスト(および成功)できます。しかし、クラッシュは実際にそれを呼び出していないようです。私の考えは、CFMアプリケーションは完全なBSD信号にアクセスできず、サブセットのみであり、MachアプリケーションはReal Thingに必要であるということです。
3)MPSetExceptionHandler。十分に文書化されていません。ハンドラーを設定しようとしました。コンパイルして実行しましたが、セグメンテーション違反を検出しませんでした。
解決
SIGSEGVではなくSIGBUSを取得しているのですか?
以下は、メモリ位置0に書き込もうとしたためにSIGBUSをキャッチします:
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