nullポインター例外をキャッチする方法は? [複製]
-
22-07-2019 - |
質問
この質問にはすでに回答があります:
- アクセス違反の例外をキャッチしますか? 8つの答え
try {
int* p = 0;
*p = 1;
} catch (...) {
cout << "null pointer." << endl;
}
このような例外をキャッチしようとしましたが、機能しません、助けてください?
解決
「nullポインター例外」などはありません。 C ++で。キャッチできる唯一の例外は、 throw
式によって明示的にスローされる例外です(さらに、Pavelが述べたように、標準の operator new
、によって本質的にスローされる標準C ++例外dynamic_cast
など)。 C ++には他の例外はありません。 nullポインターの参照解除、ゼロ除算などはC ++で例外を生成せず、未定義の動作を生成します。そのような場合に例外をスローしたい場合は、これらの条件を手動で検出し、明示的に throw
を実行するのはあなた自身の責任です。これがC ++での動作です。
他に探しているものは、C ++言語ではなく、特定の実装の機能です。たとえば、Visual C ++では、システム/ハードウェアの例外を「変換」できます。 C ++の例外になりますが、この非標準の機能には価格が付随するため、通常は支払う価値がありません。
他のヒント
できません。 nullポインターの逆参照はシステムの問題です。
Linuxでは、OSはアプリケーションでシグナルを生成します。シグナルの処理方法については、 csignal をご覧ください。 「キャッチ」する1つは、 SIGSEGV
の場合に呼び出される関数をフックします。ここで、プログラムを正常に終了する前に、いくつかの情報を印刷してみることができます。
Windowsは structured-exception-handling 。前のリンクで概説したように、インストリスティック __ try / __ except
を使用できます。私が書いた特定のデバッグユーティリティでそれをした方法は、関数 _set_se_translator
(フックに厳密に一致するため)。 Visual Studioで、SEHが有効になっていることを確認します。その関数を使用すると、システムがアプリケーションで例外を発生させたときに呼び出す関数をフックできます。あなたの場合、 EXCEPTION_ACCESS_VIOLATION
で呼び出します。その後、例外をスローして、最初に例外がスローされたかのように例外を伝播させることができます。
null(または配列の最後を過ぎたポインター、またはランダムな無効なポインター)を逆参照すると、未定義の動作が発生します。 「キャッチ」するための移植可能な方法はありません。それ。
try
を使用して、 Visual Studio であらゆる種類の例外(ゼロ除算、アクセス違反など)をキャッチする非常に簡単な方法があります。 catch(...)
ブロック。
マイナーなプロジェクトの調整で十分です。プロジェクト設定で / EHa
オプションを有効にするだけです。 プロジェクトのプロパティ-&gt;をご覧ください。 C / C ++-&gt;コード生成-&gt; Enable C ++ Exceptionsを&quot; Yes With SEH Exceptions&quot; に変更します。それだけです!
詳細はこちら: http://msdn.microsoft.com/ en-us / library / 1deeycx5(v = vs.80).aspx
C ++は、ポインターチェックを行いません(ただし、一部の実装は可能だと思います)。 nullポインターに書き込もうとすると、ハードクラッシュが発生する可能性が高くなります。例外はスローされません。これをキャッチしたい場合は、書き込む前に自分でポインタの値を確認する必要があります。
一般的にはできません。たとえできたとしても、漏れを起こした潜水艦にバンドエイドをかけるようなものです。
障害のあるアプリケーションは、クラッシュしたアプリケーションよりもはるかに多くの損害を与える可能性があります。ここでの私のアドバイスは、クラッシュさせてからクラッシュした理由を修正することです。リンス。繰り返します。
他の人が言ったように、C ++ではこれを行えません。
より広い意味で言えば、キャッチできる言語であっても、nullポインターに触れない方が良いでしょう。あなたの顔に既に爆破されているエラーをキャッチし、それが起こらなかったようにそのまま進むことを決定することは、良いコーディング戦略ではありません。 nullポインターの逆参照、スタックオーバーフローなどは、壊滅的なイベントと見なされ、言語で異なる反応が許可されている場合でも、防御的に回避する必要があります。
これを行うプラットフォームに依存しない方法はありません。 Windows / MSVC ++では、 __try /を使用できます。 __except
しかし、とにかくそれを行うことはお勧めしません。セグメンテーション違反からほぼ確実に正しく回復することはできません。
必要に応じて、自分でポインタを確認して投げることができます...
if (p == nullptr) throw std::exception("woot! a nullptr!")
p->foo();
もちろん、これは問題をデバッグするためだけのものです。nullptrは最初に発生するべきではありません:)
簡単な答え-このようなバグはプロセス自体を破壊する可能性があるため、移植可能または標準的な方法ではできません。
長めの答え-思っている以上のことができ、クラッシュするプログラムのデフォルトよりも確実に多くのことができます。ただし、次の3つの点に注意する必要があります。
1)これらのバグは例外よりも深刻であり、多くの場合、ロジックの例外として存在することはできません。
2)それらの検出とライブラリ処理は、一般消費向けのクリーンな抽象インターフェイスを提供できる場合でも、バックエンドでプラットフォームに依存します。
3)常にいくつかのクラッシュが発生するため、終了前にそれらを検出することさえできません。
基本的に、セグメンテーション違反やヒープ破損などの障害は、プログラムを実行している実際のプロセスを破損しているため、例外ではありません。プログラムにコーディングしたものはすべて例外処理を含むプログラムの一部であるため、プロセスが終了する前に素晴らしいエラーメッセージを記録すること以外は、不可能ではない場合があります。 POSIXでは、OSは信号システムを使用してこのような障害を報告します。コールバック関数を登録して、終了する前にエラーを記録できます。 Windowsでは、OSがそれらを通常の例外に変換することがあり、これをキャッチして回復することができます。
ただし、最終的には、このような悪夢に対して防御的にコーディングすることをお勧めします。特定のOSには、プロセスが終了する前に原理的にさえ検出できないほどひどいものがあります。たとえば、独自のスタックポインターを破損させると、クラッシュがひどくなり、POSIXシグナルコールバックでも見られなくなります。
VC ++ 2013(および以前のバージョン)では、例外にブレークポイントを設定できます:
- Ctrl + Alt + Deleteを押します(例外ダイアログが開きます)。
- 「Win32例外」を展開する
- 「0xC0000005アクセス違反」を確認します;例外がチェックされます。
再度デバッグを行うと、null参照解除が発生したときにブレークポイントに正確にヒットします。
c ++にはNULLポインター例外はありませんが、同じものをキャッチしたい場合は、独自のクラス実装を提供する必要があります。
以下は同じ例です。
class Exception {
public:
Exception(const string& msg,int val) : msg_(msg),e(val) {}
~Exception( ) {}
string getMessage( ) const {return(msg_);}
int what(){ return e;}
private:
string msg_;
int e;
};
今ではNULLポインターチェックに基づいて、 throw(Exception(&quot; NullPointerException&quot;、NULL));
のようにスローできます。
以下は同じものをキャッチするためのコードです。
catch(Exception& e) {
cout << "Not a valid object: " << e.getMessage( )<< ": ";
cout<<"value="<<e.what()<< endl;
}