『Object reference not set …』の解決方法

タグの編集
投稿者 mabzou  (社会人) 投稿日時 2010/3/11 04:05:06
作成中のVBアプリにて
『Object reference not set to an instance of an object』
というものが発生して困っています。
発生箇所、タイミングはわかりません。
動作環境はVB2005Express Editionです。

抽象的な質問ですのでピンポイントな回答は求めていません。
そこで、このようなエラーが発生した方が居ましたらお教え願います。

●どのような原因で発生しましたでしょうか。
●何をする事で解決しましたでしょうか

解決できなかった方は原因だけでも結構です。
どなたかお教え願います。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/3/11 06:18:17
『Object reference not set to an instance of an object.』というのは、
NullReferenceException の例外を意味しています。通常、日本語環境下では、
『オブジェクト参照がオブジェクト インスタンスに設定されていません。』の
エラーメッセージが表示されるはずですが、カルチャが英語になっている場合や
日本語ランタイムが無い環境で動作させると、英語のメッセージになります。


発生させるのは簡単で、「Nothing」な変数に対して、メソッドやプロパティを
呼び出そうとした場合に発生する事が知られています。たとえば、
 Dim s As String = Nothing
 MsgBox(s.Length)
などで、同様のエラーメッセージを発生させることができます。

英語版/日本語版のメッセージを出すなら:
Dim s As String = Nothing
System.Threading.Thread.CurrentThread.CurrentUICulture = New System.Globalization.CultureInfo("en-us")
Try
    MsgBox(s.Length)
Catch ex As NullReferenceException
    MsgBox(ex.Message)
End Try
System.Threading.Thread.CurrentThread.CurrentUICulture = New System.Globalization.CultureInfo("ja-jp")
Try
    MsgBox(s.Length)
Catch ex As NullReferenceException
    MsgBox(ex.Message)
End Try
投稿者 ヴァン  (社会人) 投稿日時 2010/3/11 19:06:49
>発生箇所、タイミングはわかりません。

1行ごとにブレークポイントを設定しても判りませんか?
投稿者 るしぇ  (社会人) 投稿日時 2010/3/11 21:57:09
NullReferenceException の例外は、掲示板上でもよく見かける基本的なエラーですね。

>●どのような原因で発生しましたでしょうか。
参照型のインスタンス生成の知識が無い人が、見よう見まねで
どっかからコピペしたコードを繋げてプログラムした場合に、
変数の中身が空っぽのまま操作して出る場合が多いです。

>●何をする事で解決しましたでしょうか
デバッグして、変数の中身を一つ一つ確認することで空っぽの
変数を探し、そこに設定すべきインスタンスを格納。
投稿者 mabzou  (社会人) 投稿日時 2010/3/11 22:25:48
3名の方々、ありがとうございます。
コード量が膨大で、再現性が低いので、テンパりました。
意味は実体の無い物を参照してエラーになっているという事なんですね。

再現性も低いので根気が要りそうですが、細かく調べようと思います。

ありがとうございました。
投稿者 mabzou  (社会人) 投稿日時 2010/3/17 01:04:46
例外発生箇所、タイミングを掴めましたが、肝心の原因が解りません。
また、どなたかアドバイス頂けないでしょうか?

例外発生箇所は、作成アプリのメインフォームのWndProc関数内でした。
ただ、この中で例外が発生すると、『細かい原因はOSしか解らなくなってしまうのでは?』
と私の認識なのですが、個人でこの先は解析可能なのでしょうか?

ちなみに例外発生時のWndProcの引き数、
System.Windows.Forms.Messageの内容ですが、

m.Msg     24
m.WParam  1
m.LParam  0
m.Result  0
という内容でした。

この事から、WM_SHOWWINDOWが原因という事までは解っている感じです。
描画という事は、フォームのLoad内に例外が潜んでいるのでしょうか?

また、毎回同じ動作をさせていても、例外が起きるのは何十回に1回ペースというのも
腑に落ちません。何かに対してnothingを代入していて、それを参照しているのなら、
100回起動したら、100回発生しそうな気がするのですが。
投稿者 GV  (中学生) 投稿日時 2010/3/17 01:28:13
そしたらさ、Loadから呼ばれる関数の頭にExitかけてデバッグしたら?
それでだめならLoadが原因。エラー出なかったら他のとこ。Exitつける関数減らしてしらみつぶしに。
投稿者 mabzou  (社会人) 投稿日時 2010/3/17 01:56:06
GVさん、ありがとうございます。
『自分でLoad内に例外が潜んでいるかも』
と書いておいて、おかしい話ですが、
Load内ではありませんね。

全関数にtry catchを入れて、catchされたら、
ex.StackTraceをログに残すようにしたのを忘れてました。
失礼しました。

ログに残っているStackTraceを見ると、WndProcの
StackTraceしかないので、途方に暮れている感じです。
どこかの関数のスタックトレースがあれば、
そこに的が絞れるのですが。
投稿者 GV  (中学生) 投稿日時 2010/3/17 02:21:43
という何十回に1回ペースなんですか・・・
全部ログってみて例外発生するときとしないときで比べてみたら?
投稿者 mabzou  (社会人) 投稿日時 2010/3/17 03:16:53
GVさん、迅速な回答ありがとうございます。
全部ログというのはどのようにすればいいんでしょうか?

StackTraceの羅列になると見にくいので、
全関数で、例外が起きた時のみ、ログを取るようにしています。

その状況で、正常時と、例外発生時のログの差分が
WndProcの例外の有無でしか無いです。
他の関数では、例外が起きたログが無いのです。

そして共通しているのは、まだ数回しか見てませんが、
WndProcで
m.Msg     24
m.WParam  1
m.LParam  0
m.Result  0
の時に例外が発生しているという点です。
投稿者 GV  (中学生) 投稿日時 2010/3/17 03:30:22
返答遅れました。
全部ログっていうのは「ログ」というかはあやしいですが、「イミディエイトウィンドウ」機能で変数を全部観察して覚えておくてきなことです。わかんなかったらすみません。
これから塾に行ってくるので、あとは他の人にタッチしてください。
投稿者 neptune  (社会人) 投稿日時 2010/3/17 04:10:18
エラーコードの取得は試してみましたか?
http://msdn.microsoft.com/ja-jp/library/system.runtime.interopservices.marshal.getlastwin32error(VS.80).aspx
「Win32 APIのWin32エラー・コードを取得するには」
http://www.atmarkit.co.jp/fdotnet/dotnettips/740win32errcode/win32errcode.html
投稿者 mabzou  (社会人) 投稿日時 2010/3/17 18:19:16
GVさん、ありがとうございます。

るしぇさんからも、アドバイス頂いているのですが、
変数を全て見るのが正しい方法と思います。
ですが、変数の数が膨大でコントロールも入れると
ちょっと現実的な方法ではないと思ってます。


neptuneさん、ありがとうございます。

エラーコード取得の実装方法、解析方法まで教えて
頂いてありがとうございます。
wndprocに実装しようとしたのですが、
『'System.Runtime.InteropServices.DllImportAttribute' 
はインスタンス メソッドに適用できません。』
と表示されます。
ひょっとして、wndprocに実装しろという意味ではなかったりしますか?
投稿者 neptune  (社会人) 投稿日時 2010/3/17 19:44:38
こんにちは

>wndprocに実装しろという意味ではなかったりしますか? 
その意味だったんですが、出来ないんですねぇ。

実はWin32API getlasterror関数でエラーを吐き出させたら解決に結びつくのではと思いまして、
frameworkで実装されてないかと代わりを探してgetlastwin32errorに行き当たったので
getlastwin32errorは私も使ったことはありませんので詳しくはわかりません。m(_ _)m

とにかくどういうエラーが出ているか知らなければ話になりませんからね。
getlasterror関数が実装できれば良いのですが。これくらいしか思いつきません。
あっ、
ついでにgetlasterror関数が実装できればFormatMessageも必要ですからその旨書いておきます。

空振りでごめんなさい。
投稿者 mabzou  (社会人) 投稿日時 2010/3/18 07:25:02
neptuneさん、ありがとうございます。

 getlasterrorという関数はvbでは正確な情報が得られない?
という書き込みが有り、その代替として、Err.LastDllErrorを使うようです。
Errは他にも、Descriptionや、Numberが有るみたいです。
ちなみに、今日も例外が発生したのですが、その時の、

Err.LastDllErrorの内容が
『0』
Err.Descriptionの内容が
『オブジェクト参照がオブジェクト インスタンスに設定されていません。』
Err.Numberの内容が
『91』

というものでした……。


Descriptionの内容からして、結局、exceptionとerrって同一内容なんでしょうか……。

邪道ですが、例外が起きて、アプリが起動できなかったら、
アプリを再起動する仕組みでも作ろうかと考えてます。