強制終了 – プログラミング – Home

通知
すべてクリア

強制終了


あい
 あい
(@あい)
ゲスト
結合: 22年前
投稿: 5
Topic starter  

デバックバージョンだと普通に動きますが
リリースバージョンにして動作させるとたまに強制終了?みたいな感じで
落ちることがあります。
強制終了する原因をつきとめるにはどうすればよいのでしょうか?
強制終了の一般的な理由ってあるのですか?


引用解決済
トピックタグ
Omega
 Omega
(@Omega)
ゲスト
結合: 21年前
投稿: 2
 

強制終了はNULLポインタアクセスとかスタック破壊とかいろいろ
あるので、根気よくトレースでも残すしか方法は無いと思います。

あと、デバッグとリリースの違いの1つに未初期化ローカル変数を
0xCDに初期化する(デバッグ時)ことがあります。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

リリースビルドでデバッグ情報を埋め込む方法があります。
これでデバッグしてみてはいかがでしょう。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200205/02050104.txt


返信引用
ボコノン教徒
 ボコノン教徒
(@ボコノン教徒)
ゲスト
結合: 23年前
投稿: 90
 

リンクでMAPファイルを生成して、アドレスから落っこちている
関数を特定する、という方法もありますが。
必ず特定できる、という訳ではないですけど。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

デバッグビルドの時は、デバッグ用の情報を載せるために
メモリの確保などは大きめに取られるみたいです。
そのためにデバッグビルド時はその大きめの取られた部分に救われて
動作するけれど、リリースビルド時にはその部分がなくなるので
アクセスバイオレーションが起こる事が考えられると思います。
ですから、メモリの確保した大きさ以上にアクセスしているところが無いかを
チェックしてみてはどうでしょうか?

あと、ローカル変数でポインタ変数を使っていて初期化していないというのも
考えられると思います。
既に書かれているようにデバッグ時とリリース時ではローカル変数の状態も
違うので注意が必要でしょう。
デバッグの時でも表面化していないだけでメモリを壊している可能性は
否定できないと思いますよ。


返信引用
アイススケーター
 アイススケーター
(@アイススケーター)
ゲスト
結合: 23年前
投稿: 280
 

怪しいと思われる場所に随時、ログ出力を行いすこしづつ範囲を狭くしていく。
デバッグ出力OutputDebugStringで出力し、赤嶺氏作のデバッグもに太を使う。

というのはどうでしょう。


返信引用
あい
 あい
(@あい)
ゲスト
結合: 22年前
投稿: 5
Topic starter  

ループの最中に構造体配列のサイズを超えてアクセスしていることが
わかりました。
ここが原因であるかは限定できてはいないですが
コードでおかしそうなところはここぐらいです。
だけど、こういうものは常に強制終了にならないものなのですか?
うまくいく場合といかない場合の差はどこにあるのでしょう。
またアプリケーションエラーにはならないのでしょうか?


返信引用
アイススケーター
 アイススケーター
(@アイススケーター)
ゲスト
結合: 23年前
投稿: 280
 

 多分スタックを破壊しているのでしょう。
 構造体配列のサイズを超えてアクセスした場合、ローカル変数だと関数の戻り値等を破壊して
暴走してしまいます。

 デバッグ時はPATIOさんのおっしゃる通り
>デバッグビルドの時は、デバッグ用の情報を載せるために
>メモリの確保などは大きめに取られるみたいです。
 だと思います。
 ローカル変数ではないにしても、他の変数を破壊していることには間違いないでしょう。
 こういったバグを出さないためにも、最大値/最小値の確認をされることをお勧めします。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

うまく行く場合といかない場合の差は、MS-DOSの頃から変わってません。
参照したところにたまたまそれらしいデータが入っているか否かです。
もっとも、昔よりメモリの管理がきちんとされている現在では、
プログラムが暴走してPCが無反応とか、
突然、画面がブラックアウトして再起動とか、
そういう事態はほとんど起こらなくなりましたけれど。

例えば、参照先をポインタとして見ていて、たまたまその部分にアドレスっぽいデータが
入っており、その先もたまたま確保された範囲にいれば、それなりに動いてしまいます。
スタック変数だったりすれば、スタックエリアを越えたアクセスでもしない限り
アクセスバイオレーションにはならないでしょうし、
デバッグ情報用の領域に助けられてたまたま不正アクセスになっ
ていないというのもありです。(内部的にはデータが壊れていたりするわけですけれど)

ですから、デバッグモードでは動いているといっても今回のような不具合を内包している
可能性はあると考えてください。
下手するとリリースビルドでも見つからない事が有ります。
後でコードを追加したらスタック上の状態が変わったために突然症状が表面化するなんて
こともありますので、よく肝に銘じておきましょう。


返信引用
あい
 あい
(@あい)
ゲスト
結合: 22年前
投稿: 5
Topic starter  

例えばポインタaの構造体配列を
ループカウンタiで順次参照しています。
(a+i)->bbb
で、このiが構造体配列のサイズ以上になる場合があるのですが
(a+i)->bbbに何かを代入しているわけではなく、参照だけしている場合にも
スタック破壊したり、アクセス違反になるのですか?


返信引用
アイススケーター
 アイススケーター
(@アイススケーター)
ゲスト
結合: 23年前
投稿: 280
 

>スタック破壊したり、アクセス違反になるのですか?
 スタック破壊は無いでしょうが、アクセス違反になる可能性はあります。
 範囲外をアクセスした場合に他の変数でメモリエリアが確保されていればアクセス違反
にはならないでしょう。
 簡単なテストプログラムを作成して確認されてはいかがでしょう。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

スタック破壊やメモリ内容の破壊はデータの書き込みの場合なので
参照の場合はアクセス違反ですね。
参照した結果、とんでもなく大きな数字でそれでループが回っていたりしたら
これまた怖い話ですけれど。

MS-DOSの頃は、アクセス違反になるような行為でもそれなり突っ走って挙句の果てに
ブラックアウトしてリセットがかかったりしましたが、
最近のOSはメモリ管理がしっかりしているので変なアクセスをするとアクセス違反で
エラーになるわけです。
その辺はOSのおかげ。
ようは触っちゃいけない領域に達するとOSがガードしてくれていると。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました