VC++6.0(MFC)で作成したプログラムでの、例外エラー発生箇所の特定が
出来ずに困っております。
実行環境は、Windows NT 4.0です。
例外発生時のイベントログを確認すると、エラー発生箇所のアドレスが
分かり、いつも"12b6fc"付近なのです。
例外番号は、c0000005 (アクセス違反)です。
しかし、タスクリストを見てもこのアドレスに何がロードされているか
記載されておりませんので、何が原因で発生しているのかわかりません。
このようなアドレスが指定された場合には、どのように対処すれば良い
でしょうか。
自分の作成したプログラムのメモリアクセスに問題があると考え、何度も
確認したのですが、不具合が見つかりません。
たとえば、PCに搭載しているメモリが少なすぎて、このようなことが発生
したりするようなことなども、原因としてあるのでしょうか。
ちなみに、メモリは64MBで、使用可能メモリは約60MB(4MBをボードが使用)
となっております。
>例外番号は、c0000005 (アクセス違反)です。
普通に考えれば、文字通りのエラーだと思われます
>自分の作成したプログラムのメモリアクセスに問題があると考え、何度も
>確認したのですが、不具合が見つかりません。
Debugでテストするとか、イベントログで確認ではなく、自前でログを吐き出すようにしてみるとかしてみました?
このエラーは、ほとんどの場合、文字変数の使い方に問題があるはずです
しむさん、ご回答ありがとうございます。
このプログラムですが、装置の制御プログラムでして、
実は手元にございません。
したがって、現在入手できた情報がワトソンログでした。
発生頻度も、数日に1回程度(連続運転)ですので、テストが難しいです。
発生箇所の心当りが無く、頻度もばらばらですが、自前でログを吐き出す
とは、具体的にどのような方法がありますでしょうか。
また、Debugでテストとは、Debugモードでコンパイルしたものを実行する
という意味ですか、それとも開発環境上から実行するのでしょうか。
文字変数については、再度チェックいたします。
よろしくお願いいたします。
> 発生箇所の心当りが無く、頻度もばらばらですが、自前でログを吐き出す
> とは、具体的にどのような方法がありますでしょうか。
私が取りあえず、問題箇所のおおまかな場所を特定するのによくやる方法を紹介しておきます。
(1)ソースの適当な位置に、複数箇所、ファイルにログ(適当な文字列)を
出力させるコードを追加する。
(2)実行させる。
(3)エラーが出たところで、出力されたログファイルを回収する。
(4)ログファイルの最後に出力されている文字列を調べる。
ここで、最後に出力された文字列を出力するソースと、本来なら次に文字列を出力するソースの部分との間に、
問題が発生する原因のソースが含まれている可能性が高いです。
さらに、文字列を出力する部分を先の見つかった範囲内に、
細かく文字列を出力するソースを追加して、先と同様のことを行います。
これを繰り返すことにより、大半の場合は、その大まかな箇所を特定できますので、
その部分のソースをよく調べて下さい。
#昔、ソースデバッガなど知らなかったときは、この方法だけで、よくデバッグしてました。
#今でも、スレッド部分のデバッグなどでは、よく使用していますが。。。
OutputDebugString()でログを残すのが簡単だと思います。
この文字列を拾うフリーソフトもありますので、VCのインストールの
必要もなし。
http://www.vector.co.jp/soft/winnt/prog/se278126.html?y
>OutputDebugString()でログを残すのが簡単だと思います。
あっ、そうですね。
私も最近OutputDebugString()の存在を知り、この関数を使用したりしてしています。
#Windows以前のDOS時代や、またく組込みシステムで、別アプリが使用できないような環境での開発が多く、
#未だにファイルにfprintf()でログを出力する方法も、活躍しています。
#ま、このような方法も知っていれば、役に立つときがあるかもしれませんので、参考程度に。
KING・王さん、PSBさん、ご回答ありがとうございます。
ログファイルを残したいのですが、本プログラムは制御周期30msec程度
の制御プログラムで、一連のシーケンスを延々と繰り返すようになって
おります。不具合頻度も数日に1回ということで、ファイルサイズが
膨大になってしまうことと、制御周期が遅くなってしまうのを恐れて、
断念しておりました。
同様な仕掛けで、画面上のテキストボックスに、現在動作している箇所
を表示するようなものをつけていて、プログラムが不具合を起こした場所
の特定を試みているのですが、不具合が発生すると一瞬にしてダイアログが
消滅してしまう(例外エラーのダイアログなど出ずに、勝手に終了)状況
ですので、役に立ちません。
いつも、突然プログラムが消滅して、残っているのはワトソンログだけ
になります。
DeMon.exe、見せていただきました。これは、便利そうですが、このプロ
グラムに対して、何日間も1秒間に数百ものログを、延々と出力しても
問題ないのでしょうか。
ワトソン博士は,COFF形式のデバッグ情報を付加しておけば関数名をログに残してくれたはずですが。
mapファイルと突き合せてみれば,アドレスだけでも役に立つかもしれません。
ワトソンログでの、アドレスはいつも"12b6fc"付近なのですが、
mapファイルを確認しても、そのようなアドレスが見当たらず困っております。
>COFF形式のデバッグ情報を付加
とは、VC++6.0でどのように設定すれば良いのでしょうか。
dbmon.exe というユーティリティが存在することを知りました。
これだと、延々と出力しても良さそう(?)なので、関数名を
都度出力して、不具合箇所を探してみることにします。
直接役に立つかどうかわかりませんが、問題個所の
Release版のアドレスが分かっているらしいので、
以下の手法がつかえるかもしれません。
DebugとReleaseではコードのメモリ配置がずれるので
実際に稼動中のRelease版が吐いたエラーアドレスから
問題のコードを特定するのは困難ですよね。
でも、手があります。
普通 Release版にはブレークポイントを設定できないのですが、
ソースの実行文として、
__asm
{
int 3h
}
と書くことでブレークさせることができます。
これはアセンブラレベルで記述するブレークポイントです。
これを一つづついろいろな場所に埋め込み、Releaseでコンパイルし、
開発環境内で実行させます。そして埋め込んだ位置でブレークした時の
アドレスを見ます。
1つづつ埋め込むのは大きくアドレスがずれないようにするためです。
この方法で問題個所を発見できたことがあります。
トリッキーな方法と、敬遠されるかもしれませんが。(^^;;
ツイート | ![]() |