MFC VC++6.0 XP
エディターを作成中なのですが、assertなどでプログラムがストップする場合に、先に
編集中のファイルをテンポラリファイルにセーブしてから、プログラムを終了するよう
に、一度assertをインターセプトするようなことは、できないのでしょうか?
お詳しい方、よろしくお願いします。
正常終了(exit)なら atexit で終了時のハンドラを登録できますが、
assertによる異常終了はこれでもハンドルされません。
既にあるようにトラップは標準的な方法では無理ですが、C言語であれば
assertで呼ばれるabortがファイルストリームをフラッシュすることは
言語仕様に規定があるので(ISO/IEC9899:1999)、
assertするような処理の前に常にテンポラリファイルに吐き続けていれば、
それはおそらく残るかと。
# そもそも、assert/abortなんて実行時に起きたらいけないものなわけで、
# 起きないようにデバッグする方を考えるべきだと思いますが。
επιστημηさん、bunさん、レスありがとうございます。
上司の男の方に聞くと、昔は瞬間停電とかの対策で、
なんか、マシンが落ちる前に、なんらかの処理が必要だったそうですが、
そういうことは、もう考える必要がないんですね。
エディターが編集途中で落ちちゃうと致命的なので、がんばってバグとりすることにし
ます。ありがとうございました。
質問の意図が分からないのでなんともですが、
Banさんが言われている通り、assertが出ない状態にまでするのが前提ですし、
あと、Releaseモードではassertが出るような状態になっても出ずに走ってしまうので
その場では落ちなくても先々でおかしくなるとかそういう事になります。
なのでassertはむしろありがたい物なんです。
デバッグ中に関してはassertで止まった時は仕方が無いとあきらめるしか無いと
思いますよ。
あと、瞬間停電とassertを一緒にしてはいけません。
瞬間停電はプログラマの責任では有りませんが、
assertが起きるのはプログラマの責任です。
それに瞬間停電を恐れるのであれば、
今は無停電電源装置が割りと安く出回っていますから
そっちで対策で来ますよね。
PATIOさん、レスありがとうございます。
エディタを作っていて、落ちまくります。実際編集していて、落ちて、編集内容がパー
になってしまうと、たいがいへこみます。
なんとか、簡単にそこのところだけでも、対策できないかなぁ・・・と質問してみたの
ですが、どうも、まず、バグとりに励むしかないようですね。
ありがとうございました。
ランタイム内で落ちてるとだめだけど、自分で入れたアサートないし、
コードインクルードなら当該のコードを{__asm int 3}で
置き換えるとデバッグできます。何度も救われていますint 3 には(^^;)。
?
そんなことしなくても、[再試行(R)]を選択すればデバッグブレークしてくれますけど。
強制的にデバッグブレークをするなら _CrtDbgBreak(); でもいいし。
第一 int 3 割り込みでプログラムを停止させるならそこにブレークポイント仕掛ければ
いいことだし。
そんなことを言っているのではない?
仲澤@失業者 さん、maru さん、レスありがとうございます。
仲澤@失業者 さんのレス内容についてちょっとしらべてみました。
__asm は、インラインアセンブラの記述で、
> INT 3 命令は、デバッグ例外ハンドラをコールすることを目的とする特別な
> 1 バイト・オペコード(CC)を生成する。
となっていますね・・・。
いまひとつ、どうやって使うのか、わからないんですが・・・
よろしければ、アドバイスをいただければ、幸せです。
int 3
3番目の割り込み(interrupt)を発生させるX86のオペコード(命令)です。
3番目の割り込みはデバッグ例外ハンドラと呼ばれ一般にデバッガで使用されます。
デバッグ例外ハンドラが起動されると、そのOSにインストールされたデバッガが起動
されるようにOSが設定されています。VCがインストールされている環境ではVCが起動
され、その命令が実行された場所のデバッグが出来るようになります。
私が書いた_CrtDbgBreak();も内部では同じことをやっているはずですが、こちらは
デバッグモードでコンパイルしたプログラムしかデバッグブレークしません。
デバッガでブレークポイントを仕掛けて実行すると、その位置でプログラムが停止し
ますが、実はデバッガがその位置の命令を int 3 に置き換えて実行しているんです。
つまり、仲澤@失業者さんがやっていることはデバッガでブレークポイントを設定し
ているのとほぼ同じことをやっているわけです。
>エディタを作っていて、落ちまくります。実際編集していて、落ちて、編集内容がパー
>になってしまうと、たいがいへこみます。
>なんとか、簡単にそこのところだけでも、対策できないかなぁ・・・と質問してみたの
>ですが、どうも、まず、バグとりに励むしかないようですね。
一応下記のようにあらゆる例外をキャッチするようにしておけば
実行時の強制終了まで補足されてしまいます。
try {
//処理
}
catch(...) {
//ここでエディタの内容を保存?
throw;
}
>実行時の強制終了まで補足されてしまいます。
補足じゃなくて捕捉です。
maruさん、わざわざ説明してもらってすみません。
少し補足すると、既にコード済みのアサート相当コード
「MyAssert(n)」に対して
#define MyAssert(n) if(n){__asm int 3}
みたいなコードををプリコンパイルヘッダに入れると、
便利ですよと言いたかったわけです。
この方法の良いところはプリコンパイル以外はいじらなくても
また、いちいち手動でブレークポイントを設定しなくても
アサート抜けを全てブレークできることです。
assert っつのは「プログラムがバグっていることの証明」なわけで、
assert したときに「データを正しく保存する」ことが可能かどうかなど不明。
だって明らかにバグっていることがわかった状態なわけだぜ。
・エディタが保持しているデータが破壊されている
・保存すべきファイル名が破壊されている
その他、何が正しくて何が破壊されているか、なんてことはわかりっこない。
俺ならば「不正なデータは保存しないほうが安全だ」と思うわけだ。
その意味で assert が出ないようにバグ修正するなんてのは必須なのであって
assert が出たときに何か対処する方策がないか?なんて調べるのは道を外れている。