web-dev-qa-db-ja.com

nullポインター例外をキャッチする方法は?

  try {
        int* p = 0;
        *p = 1;
    } catch (...) {
        cout << "null pointer." << endl;
    }

私はこのような例外をキャッチしようとしましたが、うまくいきません、助けてください?

39
mindhacks

C++には「nullポインタ例外」というものはありません。キャッチできる唯一の例外は、throw式によって明示的にスローされる例外です(さらに、Pavelが述べたように、標準のoperator newdynamic_castなどによって本質的にスローされる標準C++例外もあります)。 C++には他の例外はありません。 NULLポインターの参照解除、ゼロ除算などはC++で例外を生成せず、未定義の動作を生成します。そのような場合に例外をスローしたい場合は、これらの条件を手動で検出し、throwを明示的に行うのはあなた自身の責任です。それがC++での動作です。

あなたが探していると思われるものは何でも、C++言語ではなく、特定の実装の機能に関係しています。たとえば、Visual C++では、システム/ハードウェアの例外をC++の例外に「変換」できますが、この非標準の機能には価格がかかり、通常は支払う価値がありません。

56
AnT

できません。 nullポインターの逆参照はシステムの問題です。

Linuxでは、OSはアプリケーションでシグナルを発生させます。 csignal を見て、シグナルの処理方法を確認してください。 1つを「キャッチ」するには、SIGSEGVの場合に呼び出される関数をフックします。ここで、プログラムを正常に終了する前に、いくつかの情報を印刷してみることができます。

Windowsは structured-exception-handling を使用します。あなたはinstristics __try/__except、前のリンクで説明したとおり。私が書いた特定のデバッグユーティリティでそれをしたのは、関数 _set_se_translator (フックに厳密に一致するため)。 Visual Studioで、SEHが有効になっていることを確認します。その関数を使用すると、システムがアプリケーションで例外を発生させたときに呼び出す関数をフックできます。あなたの場合、それはEXCEPTION_ACCESS_VIOLATION。その後、例外をスローして、そもそも例外がスローされたかのように例外を伝播させることができます。

25
GManNickG

Null(または配列の最後を過ぎたポインター、またはランダムな無効なポインター)を逆参照すると、未定義の動作が発生します。それを「キャッチ」するポータブルな方法はありません。

9
Pavel Minaev

tryを使用して、Visual Studioであらゆる種類の例外(ゼロ除算、アクセス違反など)をキャッチする非常に簡単な方法があります。 -> catch (...)ブロック。

プロジェクトを微調整するだけで十分です。プロジェクト設定で/EHaオプションを有効にするだけです。 プロジェクトのプロパティ-> C/C++->コード生成-> C++例外を有効にするを「SEH例外ではい」に変更するを参照してください。それでおしまい!

詳細はこちら: http://msdn.Microsoft.com/en-us/library/1deeycx5(v = vs.80).aspx

7

C++はポインターチェックを行いません(ただし、いくつかの実装は可能だと思います)。 nullポインターに書き込もうとすると、ほとんどの場合、クラッシュが激しくなります。例外はスローされません。これをキャッチしたい場合は、書き込む前に自分でポインタの値を確認する必要があります。

5
Nate C-K

一般的にはできません。たとえできたとしても、漏れを起こした潜水艦にバンドエイドをかけるようなものです。

障害のあるアプリケーションは、クラッシュしたアプリケーションよりもはるかに多くの損害を与える可能性があります。ここでの私のアドバイスは、クラッシュさせてからクラッシュした理由を修正することです。リンス。繰り返す。

3
0xC0DEFACE

これを行うプラットフォームに依存しない方法はありません。 Windows/MSVC++では、 __ try /__ exceptを使用できます

しかし、とにかくそれを行うことはお勧めしません。セグメンテーション違反からほぼ確実に正しく回復することはできません。

1
Axel Gneiting

他の人が言ったように、これをC++で行うことはできません。

もっと広い意味で言えば、キャッチできる言語であっても、nullポインターに触れないほうがいいでしょう。あなたの顔にすでに爆破されているエラーをキャッチし、それが起こらなかったようにそのまま進むことを決定することは、良いコーディング戦略ではありません。ヌルポインターの逆参照、スタックオーバーフローなどは、壊滅的なイベントと見なされ、言語で異なる反応が許可されている場合でも、防御的に回避する必要があります。

1
asveikau

あなたが望むなら、あなたは自分自身をチェックして投げることができます...

if (p == nullptr) throw std::exception("woot! a nullptr!")
p->foo();

もちろん、これは問題をデバッグするためだけのものであり、nullptrは最初に発生するべきではありません:)

0
Jan Wilmans

短い答え-このようなバグはプロセス自体を破損する可能性があるため、移植性のある方法や標準的な方法ではできません。

長い答え-あなたが思うよりも多くのことを行うことができ、プログラムがクラッシュするだけのデフォルトよりも間違いなく多くのことができます。ただし、次の3つの点に留意する必要があります。
1)これらのバグは、例外よりも深刻であり、多くの場合、ロジックの例外として提示することはできません。
2)それらの検出とライブラリ処理は、バックエンドでプラットフォームに依存しますが、公共消費向けのクリーンな抽象インターフェースを提供できます。
3)常にいくつかのクラッシュが発生するため、終了前にクラッシュを検出することさえできません。

基本的に、セグメンテーション違反やヒープ破損などの障害は、プログラムを実行している実際のプロセスを破損しているため、例外ではありません。プログラムにコーディングしたものはすべて例外処理を含むプログラムの一部であるため、プロセスが終了する前にNiceエラーメッセージを記録すること以外は、不可能ではない場合があります。 POSIXでは、OSは信号システムを使用してこれらのような障害を報告し、コールバック関数を登録して、終了する前にエラーを記録できます。 Windowsでは、OSがそれらを通常の例外に変換して、キャッチして回復できる場合があります。

ただし、最終的には、このような悪夢に対して防御的にコーディングすることをお勧めします。特定のOSには、プロセスが終了する前に原理的にさえ検出できないほどひどいものがあります。たとえば、独自のスタックポインターを破損すると、非常にひどくクラッシュする可能性があり、POSIXシグナルコールバックでもそれを認識できなくなります。

0
Zack Yezek

VC++ 2013(および以前のバージョン)では、例外にブレークポイントを設定できます。

  1. Ctrl + Alt + Deleteを押します(これにより、例外ダイアログが開きます)。
  2. 「Win32例外」を展開します
  3. 「0xC0000005アクセス違反」例外がチェックされていることを確認してください。

再度デバッグを行うと、null参照解除が発生したときにブレークポイントにヒットします。