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。十分に文書化されていません。ハンドラを設定しようとしました。コンパイルして実行しましたが、segfault をキャッチしませんでした。

4

1 に答える 1

3

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
于 2009-03-05T13:57:31.217 に答える