DOBON.NET DOBON.NETプログラミング掲示板過去ログ

構造体代入時のNULL参照例外

環境/言語:[XPE, VB.NET(2010Express), .NET4.0]
分類:[.NET]

お世話になります。

構造体変数への代入時に
"Object reference not set to an instance of an object."
というメッセージの例外が出るときがあるのですが、
なぜ NULL 参照となるのか、原因がわかりません。

コードは次の通りで、問題の個所は FuncA の冒頭です。

Private Function FuncA(ByRef c1 As ClassA, _
                       ByRef Optional v1 As Integer = 0, _
                       ByRef Optional v2 As Integer = 0, _
                       ByVal Optional v3 As Boolean = True) As StructA
    Dim st1 As StructA
    st1 = FuncB()        '→この行で例外が出る。

    (省略)

    Return st1
End Function

Private Function FuncB() As StructA
    Dim st2 As New StructA
    st2.init()

    (条件に合わせてstの各メンバーを設定。
     但し例外になる場合もならない場合も同じパスを通る。)

    Return st2
End Function

Public Structure StructA
    Public value As Integer
    Public message As String
    Public code As Integer
    Sub init()
        value = 0
        message = String.Empty
        code = 0
    End Sub
End Structure

毎回必ず例外となるわけではなく、
アプリケーションを実行し続けているとたまに発生します。
一旦発生すると、FuncA 実行時に必ず発生するようになりますが、
他の処理は問題なく動作します。
アプリケーションを終了後、再実行すると発生しなくなるので、
メモリ不足の可能性も考えたのですが、
OurOfMemoryException や StackOverFlowException ではないので、
違うのかなと。
また、実行環境が XP Embedded なのですが、
そこ固有の問題かどうかは切り分けできておらず、
デバッガ上での再現はまだできていません。

以上ですが、何か心当たりがありましたら、助言頂けると助かります。
よろしくお願い致します。
  • 題名: Re[1]: 構造体代入時のNULL参照例外
  • 著者: 魔界の仮面弁士
  • 日時: 2012/01/12 13:48:06
  • ID: 29584
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No29583に返信(matuさんの記事)
> 以上ですが、何か心当たりがありましたら、助言頂けると助かります。
StructA で Nothing になるものがあるとすれば、
message As String ぐらいのものですよね。

省略された部分に原因があるのかも知れませんが、少なくとも
提示されたコード部分だけでは問題無さそうに見えます。

エラー発生時のスタックトレースを記録することはできないでしょうか。
配置もデバッグビルドのままにした上で。
■No29583に返信(matuさんの記事)

> (条件に合わせてstの各メンバーを設定。
> 但し例外になる場合もならない場合も同じパスを通る。)
この辺があやしい。
魔界の仮面弁士さん、shuさん、ご回答ありがとうございます。


魔界の仮面弁士さん

デバッグビルドで Exception.StackTrace プロパティを出力していました。
そこから、FuncA の該当行でNULL参照例外が発生したことまでは
わかったのですが、そこで行き詰ってしまい質問させて頂いた次第です。
もしかして、コールスタックのことではなく、
もっと突っ込んだ情報を取得できるということでしょうか?

> StructA で Nothing になるものがあるとすれば、
> message As String ぐらいのものですよね。

それも疑ったのですが、message が Nothing でも st1 への代入自体は
問題ないと思います。
テスト的に FuncB で message を Nothing にしてもみましたが、
例外は発生しませんでした。


shuさん

確かにあやしく思える書き方でした。申し訳ありません。
FuncB をもう少し詳しく書くと以下のようになります。

Private Function FuncB() As StructA
    Dim st2 As New StructA
    st2.init()

    st2.code = 0
    If 条件1 Then
        st2.message = "Error 1"
        st2.code = 1
        Return
    End If
    If 条件2 Then
        st2.message = "Error 2"
        st2.code = 2
        Return
    End If
    (以降同様のコードが続く)

    Return st2
End Function

st1 に格納する値に問題があれば、FuncB 内で例外が出るはずですし、
例え message に Nothing が設定されたとしても例外にはならないですし。

st1 への代入後に続く処理で例外が出るならわかりますが、
st1 への代入時なので、st1 もしくは st2 そのものが消えないと
NULL参照にはならないように思えてしまって。
値型なので Nothing にすることもできませんが…
■No29602に返信(matuさんの記事)
>> 環境/言語:[XPE, VB.NET(2010Express), .NET4.0]
Windows XP Embedded でしたか。あれって、.NET 4 に非対応なのでは?

インストールできてしまうかどうかは別として、公式には
.NET Framework 3.0 までの対応になっていた気が。(うろ覚え)
3.5 ですら Windows XP Embedded SP2 FP2007 には非対応だったような…。
(3.5 には Windows Embedded Standard 2009 以降の Embedded OS が必要)


> デバッグビルドで Exception.StackTrace プロパティを出力していました。
実際に例外が発生した場所よりも外側でエラー停止することもあるため
(たとえば、DebuggerHiddenAttribute が付与されていた場合)、
もしかしたら Visual Studio が自動生成したコード等で
エラーになっているのかと思ったのですが……StackTrace 自体も
その行を指しているのですね。

あと調べるとしたら .InnerException と .Data ぐらいですが、
たぶん例外からは、今以上の追加情報は得られないかも。


> 値型なので Nothing にすることもできませんが…

構造体を Webサービスとして公開すると、クライアント側では
それがクラスとして見えたりしますが、そういう話でも無いですよね…。
■No29604に返信(魔界の仮面弁士さんの記事)
> Windows XP Embedded でしたか。あれって、.NET 4 に非対応なのでは?

あちゃー。仰る通りですね。
他社ソフトの都合で .NET 4 にするよう指示をもらっていたのですが、
客先も私も対応環境の確認が抜けていたということですね。
やってしまったなぁ。

> 構造体を Webサービスとして公開すると、クライアント側では
> それがクラスとして見えたりします

今回は違いますが、そうなんですね。勉強になります。

とりあえず、以下をテストしてみます。
・.InnerException と .Data を確認する
・.NET のバージョンを下げてみる
・コードの書き方を変えてみる(恐ろしい話ですが)
■No29606に返信(matuの記事)

> とりあえず、以下をテストしてみます。
> ・.InnerException と .Data を確認する
> ・.NET のバージョンを下げてみる
> ・コードの書き方を変えてみる(恐ろしい話ですが)

どこかで状況が変わってしまったのか、
前回以来、再現できないままでいます。
進展がありましたら書き込ませて頂きますが、
いつになるかわからないので、ここで解決とさせて頂きます。

みなさま、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板