概要
Visual Studio 2019でC#を使用して開発を行っている際に、デバッグモードとリリースモードで挙動が異なる現象がありましたので、備忘録として残しておきます。
対応1:「コードの最適化」の設定を疑う
Visual Studioにはコードの最適化という機能があるそうで、コンパイル時にコードを微修正してくれる機能だそうです。この設定はVisual Studio 2019だと以下から設定を変更できました。
ソリューションエクスプローラのプロジェクトを右クリック > 「「プロパティ」を選択 > 左側の「ビルド」タブを選択 > 「全般」の中にある「最適化コード」のチェックボックス
この設定がデバッグモードではチェックが外れており、リリースモードではチェックが付いていると、挙動の違いが起こる可能性があるらしいです。なのでリリースモードでもチェックを外してあげると、デバッグモードと同じように挙動するかもしれません。
対応2:「データヒント」の表示タイミングを疑う
厳密にはデバッグモードとリリースモードの違いというより、同じデバッグモードでも、とある変数 (プロパティ) のデータヒントを表示したかどうかで、その後の処理の挙動が変わるということがありました。
データヒントというのはVisual Studioのデバッグモードでブレイクポイントで特定の処理でストップした際、変数やプロパティ名をマウスオーバーするとその中身の値が確認できる機能です。
少し昔に発生したのでしっかりと覚えていないのですが、特定の場所にブレイクポイントを貼っていて、その場所でとまった際にデータヒントを使用して特定のプロパティの中身を確認していたのですが、そのデータヒントを表示するかどうかでその後の処理が変わっていました。その時は確かデータヒントを使用すると、その後の処理も想定通りの挙動となっており、使用しないと想定外の挙動 (エラー) になっていました。
最初はリリースモードで動作確認していた際に想定外の箇所でエラーになっていたことで気が付いたと思います。その特定のプロパティは実装中の処理にすごく関係が深いプロパティだったため、デバッグ中は無意識ですが必ずデータヒントを表示して中身を確認していたかなと思います。
あまり検索してもヒットしないのでここからは推測ですが、データヒントでプロパティの値を確認する際、プロパティの値を評価して表示させていると思われます。
※プロパティのGetterを走らせてからデータヒントに値を表示させているイメージ?
なので、例えばGetterの中身が複雑になっておりその時に応じて値が変わってしまう場合だと、特定の処理の前に、
- データヒントでプロパティのGetterを走らせてから処理を行う
- プロパティのGetterを走らせずに処理を行う
とデータヒントを表示するかどうかがその後の処理に影響して、挙動に差異が生じてしまうのかなと思われました。
上記の場合はもちろんデータヒントを表示せずに処理が走る方が正規のモジュールの動きなので、修正する必要があります。
今回の場合は、単に修正だけだとエラーが出る部分の直前にコードでも一度プロパティのGetterを呼び出しておく対応を行うとエラーはでませんでしたが、そもそもGetterの中身が複雑になりすぎていたので、その部分の改修も行いました。
終わりに
debugモードとreleaseモードで挙動が違う場合に、上記以外に当てはまることがあった場合はまた追記していこうと思います。