16

私のデバッグ時間の多くは、複雑なステートメントでnull参照例外を追跡するために費やされているように思われます。例えば:

For Each game As IHomeGame in _GamesToOpen.GetIterator()

なぜ、NullReferenceExceptionを取得したときに、スタックトレースの行番号を取得できますが、nullに等しいオブジェクトの名前は取得できません。言い換えれば、なぜ:

Object reference not set to an instance of an object.

それ以外の

_GamesToOpen is not set to an instance of an object.

また

Anonymous object returned by _GamesToOpen.GetIterator() is null.

また

game was set to null.

これは厳密に設計上の選択であり、コードの匿名性を保護することを目的としていますか、それともコンパイラの設計にこの情報をデバッグ時の例外に含めないという説得力のある理由がありますか?

4

5 に答える 5

11

例外は実行時のもので、変数はコンパイル時のものです。

実際、あなたの例の変数はです。式は必ずしも単純な変数ではありません。実行時に式が評価され、結果のオブジェクトでメソッドが呼び出されます。その式の値が の場合null、ランタイムはNullReferenceException. 次のことを前提とします。

Dim a as New MyObject
Dim b as String = MyObject.GetNullValue().ToString()

GetNullValue()メソッドが を返した場合、ランタイムはどのようなエラー メッセージを返す必要がありますnullか?

于 2009-02-23T18:34:21.383 に答える
3

VM によって解釈されるバイトコードにコンパイルされる Java のような言語の場合X、 field を持つクラスがxあり、その値がnull特定の参照用であるとします。あなたが書くなら

x.foo()

バイトコードは次のようになります。

push Xref           >> top of stack is ref to instance of X with X.x = null
getField x          >> pops Xref, pushes 'null' on the stack
invokeMethod foo    >> pops 'null' -> runtime exception

要点は、例のinvokeMethodのように、スタック上で操作するためにnull以外の参照を必要とする操作は、そのnull参照がどこから来たのかを知ることができず、わからないということです。

于 2009-02-23T19:23:00.487 に答える
1

デバッグのためにこれをキャッチして、オブジェクトを使用する前に Assert ステートメントを配置し、null をチェックして、意味のあるメッセージを出力する簡単な方法です。

于 2009-02-23T18:36:26.290 に答える
1

リリース ビルドでは、変数名はシンボルから取り除かれ、コードは変数用の特定のメモリ位置を持たないように最適化されることさえあるかもしれませんが、レジスタの 1 つに参照を保持するだけです (変数の使用範囲に応じて)。 )。したがって、変数の名前を参照場所から差し引くことができない場合があります。

デバッグ ビルドでは、変数に関するより多くの情報を利用できます。ただし、ビルド フレーバーに関係なく、例外オブジェクトは同じように機能する必要があります。したがって、どのフレーバーでもアクセスできる最小限の情報に基づいて動作します。

于 2009-02-23T18:37:40.173 に答える
1

いくつかのこと...

1)独自の例外を作成するときは、これを念頭に置いてください(あなたがこれに腹を立てている場合、他の何かのためにそれをすると、他の誰かがあなたに腹を立てるでしょう). 例外パスが一般的なパスであってはならないことを考えると、例外に有用な情報を持たせるために費やす時間はそれだけの価値があります。

2)一般的なプログラミングの実践者として、このスタイルを採用すると、問題がはるかに少なくなります(はい、コードは行数で長くなりますが、多くの時間を節約できます):

a) ab().c(); を実行しないでください。do x = ab(); xc(); (別の行で)そのようにして、 a が null であったか、または ab() の戻り値が null であるかを確認できます。

b) メソッド呼び出しの戻り値をパラメーターとして渡さないでください。常に変数を渡します。a(foo()); x = foo(); である必要があります。斧); これは、デバッグして値を確認できるようにするためのものです。

.net や Java などの環境が、これらの種類の例外に関するより多くの情報を持っているバージョンのランタイムを提供しない理由がわかりません。それはヌルです、など...

于 2009-02-23T18:46:51.913 に答える