5

Linux で NULL ポインター アクセスを C++ 例外に変換する方法はありますか? Java の NullPointerException に似たもの。クラッシュする代わりに、次のプログラムが正常に返されることを願っています (コンパイル時にコンパイラがこの NULL ポインター アクセスを把握できないと仮定します)。

class NullPointerException {};

void accessNullPointer(char* ptr) {
    *ptr = 0;
}

int main() {
    try {
        accessNullPointer(0);
    } catch (NullPointerException&) {
        return 1;
    }
    return 0;
}

C ++でのNULLポインターアクセスは未定義の動作であるため、標準的な方法は期待していません。x86_64 Linux / GCCでそれを行う方法を知りたいだけです。

私はこれについて非常に原始的な研究を行いましたが、可能かもしれません:

  1. Linux で NULL ポインタがアクセスされると、SIGSEGV が生成されます。
  2. SIGSEGV ハンドラ内では、プログラムのメモリとレジスタ情報が利用可能です (sigaction()シグナルハンドラの登録に使用されている場合)。プログラムを逆アセンブルすると、SIGSEGV の原因となった命令も使用できます。
  3. プログラムのメモリやレジスタを変更し、例外インスタンスを作成/偽造します (おそらく、_Unwind_RaiseException などの低レベルのアンワインド ライブラリ関数を呼び出すことによって)。
  4. 最後にシグナル ハンドラーから戻ります。通常の例外がスローされたように、プログラムが C++ スタックの巻き戻しプロセスを開始することを願っています。

以下は、GCC のマニュアル ページ (-fnon-call-exceptions) からの引用です。

トラップ命令が例外をスローできるようにするコードを生成します。これには、どこにも存在しないプラットフォーム固有のランタイム サポートが必要であることに注意してください。さらに、トラッピング命令のみが例外をスローすることを許可します。つまり、メモリ参照または浮動小数点命令です。「SIGALRM」などの任意のシグナルハンドラから例外をスローすることはできません。

この「プラットフォーム固有のランタイム」はまさに私が望んでいるもののようです。Linux/x86_64 のそのようなランタイムを知っている人はいますか? または、そのようなランタイムがまだ存在しない場合に、そのようなランタイムを実装する方法に関する情報を教えてください。

ソリューションがマルチスレッドプログラムでも機能することを望みます。

4

2 に答える 2

2

いいえ、それを行う良い方法はありませんし、あってはなりません。例外はthrow、ソース コード内のステートメントによってスローされます。これは、例外の安全性を考える上で重要です。コードを見て、例外がスローされる可能性のある場所を確認できます。さらに重要なのは、コードを見て、例外がスローされない場所を確認できることです。catch何をしても例外がスローされる可能性がある場合、句を散らかさずに例外セーフなコードを記述することは非常に困難になります。Microsoft は初期の C++ コンパイラでこれを試みました。OS の構造化された例外の上に C++ の例外処理を便乗させた結果、大惨事になりました。

于 2016-06-07T13:09:54.230 に答える