デバックバージョンだと普通に動きますが
リリースバージョンにして動作させるとたまに強制終了?みたいな感じで
落ちることがあります。
強制終了する原因をつきとめるにはどうすればよいのでしょうか?
強制終了の一般的な理由ってあるのですか?
強制終了はNULLポインタアクセスとかスタック破壊とかいろいろ
あるので、根気よくトレースでも残すしか方法は無いと思います。
あと、デバッグとリリースの違いの1つに未初期化ローカル変数を
0xCDに初期化する(デバッグ時)ことがあります。
リリースビルドでデバッグ情報を埋め込む方法があります。
これでデバッグしてみてはいかがでしょう。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200205/02050104.txt
リンクでMAPファイルを生成して、アドレスから落っこちている
関数を特定する、という方法もありますが。
必ず特定できる、という訳ではないですけど。
デバッグビルドの時は、デバッグ用の情報を載せるために
メモリの確保などは大きめに取られるみたいです。
そのためにデバッグビルド時はその大きめの取られた部分に救われて
動作するけれど、リリースビルド時にはその部分がなくなるので
アクセスバイオレーションが起こる事が考えられると思います。
ですから、メモリの確保した大きさ以上にアクセスしているところが無いかを
チェックしてみてはどうでしょうか?
あと、ローカル変数でポインタ変数を使っていて初期化していないというのも
考えられると思います。
既に書かれているようにデバッグ時とリリース時ではローカル変数の状態も
違うので注意が必要でしょう。
デバッグの時でも表面化していないだけでメモリを壊している可能性は
否定できないと思いますよ。
怪しいと思われる場所に随時、ログ出力を行いすこしづつ範囲を狭くしていく。
デバッグ出力OutputDebugStringで出力し、赤嶺氏作のデバッグもに太を使う。
というのはどうでしょう。
ループの最中に構造体配列のサイズを超えてアクセスしていることが
わかりました。
ここが原因であるかは限定できてはいないですが
コードでおかしそうなところはここぐらいです。
だけど、こういうものは常に強制終了にならないものなのですか?
うまくいく場合といかない場合の差はどこにあるのでしょう。
またアプリケーションエラーにはならないのでしょうか?
多分スタックを破壊しているのでしょう。
構造体配列のサイズを超えてアクセスした場合、ローカル変数だと関数の戻り値等を破壊して
暴走してしまいます。
デバッグ時はPATIOさんのおっしゃる通り
>デバッグビルドの時は、デバッグ用の情報を載せるために
>メモリの確保などは大きめに取られるみたいです。
だと思います。
ローカル変数ではないにしても、他の変数を破壊していることには間違いないでしょう。
こういったバグを出さないためにも、最大値/最小値の確認をされることをお勧めします。
うまく行く場合といかない場合の差は、MS-DOSの頃から変わってません。
参照したところにたまたまそれらしいデータが入っているか否かです。
もっとも、昔よりメモリの管理がきちんとされている現在では、
プログラムが暴走してPCが無反応とか、
突然、画面がブラックアウトして再起動とか、
そういう事態はほとんど起こらなくなりましたけれど。
例えば、参照先をポインタとして見ていて、たまたまその部分にアドレスっぽいデータが
入っており、その先もたまたま確保された範囲にいれば、それなりに動いてしまいます。
スタック変数だったりすれば、スタックエリアを越えたアクセスでもしない限り
アクセスバイオレーションにはならないでしょうし、
デバッグ情報用の領域に助けられてたまたま不正アクセスになっ
ていないというのもありです。(内部的にはデータが壊れていたりするわけですけれど)
ですから、デバッグモードでは動いているといっても今回のような不具合を内包している
可能性はあると考えてください。
下手するとリリースビルドでも見つからない事が有ります。
後でコードを追加したらスタック上の状態が変わったために突然症状が表面化するなんて
こともありますので、よく肝に銘じておきましょう。
例えばポインタaの構造体配列を
ループカウンタiで順次参照しています。
(a+i)->bbb
で、このiが構造体配列のサイズ以上になる場合があるのですが
(a+i)->bbbに何かを代入しているわけではなく、参照だけしている場合にも
スタック破壊したり、アクセス違反になるのですか?
>スタック破壊したり、アクセス違反になるのですか?
スタック破壊は無いでしょうが、アクセス違反になる可能性はあります。
範囲外をアクセスした場合に他の変数でメモリエリアが確保されていればアクセス違反
にはならないでしょう。
簡単なテストプログラムを作成して確認されてはいかがでしょう。
スタック破壊やメモリ内容の破壊はデータの書き込みの場合なので
参照の場合はアクセス違反ですね。
参照した結果、とんでもなく大きな数字でそれでループが回っていたりしたら
これまた怖い話ですけれど。
MS-DOSの頃は、アクセス違反になるような行為でもそれなり突っ走って挙句の果てに
ブラックアウトしてリセットがかかったりしましたが、
最近のOSはメモリ管理がしっかりしているので変なアクセスをするとアクセス違反で
エラーになるわけです。
その辺はOSのおかげ。
ようは触っちゃいけない領域に達するとOSがガードしてくれていると。