#pragma twice

KAB-studio > プログラミング > #pragma twice > 118 Version 6.18 デバッグビルドとリリースビルド再び

#pragma twice 118 Version 6.18 デバッグビルドとリリースビルド再び

前のページへ 表紙・目次へ 次のページへ

 Version 6.18
デバッグビルドとリリースビルド再び

さて今回は、デバッグする上で重要なことのひとつ、デバッグビルドとリ
リースビルドってものについて解説します
って、前にそれ教えてもらったよ?
 Ver 3.24 ( No.049 ) だね。でもちょっとだけだったでしょ
最後の4分の1だけ……
というわけで、もう少し突っ込んで見てみましょう。もちろんデバッグに
も関係あるしね
そりゃデバッグモードってゆーんだもんね。でも具体的にゆーと?
まず、一番重要なのは ASSERT() や TRACE() かな。っと、まず #ifdef 
とか思い出して
 Ver 6.06 ( No.106 ) とか Ver 6.07 ( No.107 ) だね
そのとき<条件コンパイル>ってやったでしょ。実は ASSERT() や 
TRACE() にはこの条件コンパイルが大きく関わってくるんです
何を #define するかでプログラムが変わってくるってヤツね。 ASSERT()
とかが変わる?
変わるんです。と、その前にちょっと復習

void CDebugDlg::OnButton1() 
{
    int i = 100;
    CString cStr;
    cStr.Format( "%d", i );
    MessageBox( cStr );
    // 100
}

えーっと、確か CString::Format() って TRACE() みたく、数字を 
CString に入れてくれるんだよね
そう。最後はダイアログとしてそれを表示
うん、 100 って出た。でもなんで TRACE() 使わないの?
それがミソ。でもその前に、 ASSERT() の方。今度はこれ試して

void CDebugDlg::OnButton1() 
{
    int i = 100;
    ASSERT( ++i );
    CString cStr;
    cStr.Format( "%d", i );
    MessageBox( cStr );
    // 101
}

さっきのと違うとこ…… ASERT() で i を 1 増やしてるね。でもそれだ
けだし結果も当たり前の 101 ……
うん、これはその確認。じゃ、今度はリリースビルドで試してみましょ
う。やり方憶えてる?
教えてもらった?
えーっと……あ、 Ver 3.24 ( No.049 ) で
ホントだ。えっと、【ビルド】−【アクティブな構成の設定】、んで
Release 、でいいんだよね
そうそう。それでビルドして実行してみて
ほいビルド……そういえば、なんでこれ、時間掛かるの? デバッグの時
も、最初にビルドした時って時間掛かるし
普段時間掛からないのは、前にビルドした時から変更されたとこだけビル
ドするから
あ、だから2度目からは時間掛からないんだ
大きく書き変えたりしたら、やっぱり全部ビルドし直して時間かかるよ
へー。あ、終わった。んで実行。あ
〈デバッグ情報がありません〉ダイアログは無視していいよ
ほい。と、さっきみたく普通にボタン押して……あ!  100 だ、ダイア
ログに 100 ってなってる!
そう、増えてないでしょ。つまりリリースビルドだと

    ASSERT( ++i );

の1行が丸ごとなくなっちゃうわけ
なんてこったい……
これが、前回言った〈リリースビルドだと ASSERT() が働かない〉ってこ

へぇ……あ、ちょっと試していい?
もちろん

void CDebugDlg::OnButton1() 
{
    ASSERT( 0 );
}

うわー、リリースビルドだと止まらないしダイアログも出ない……
でしょう。じゃ、なんでそうなるか見てみましょう。 MFC のインクルー
ドファイルの中に Afx.h ってファイルがあるから、その中から ASSERT() 
を探して
あ、結構上の方にあった……けど、ふたつあるよ、どっちが本物?
両方とも本物。上から見てくと……

// Afx.h

#ifdef _DEBUG
// 略。

#define ASSERT(f) \
// 略。

#else   // _DEBUG

#define ASSERT(f)          ((void)0)
// 略。

#endif // !_DEBUG

??……あ! そっか、これが条件コンパイルのとこなんだ
そゆこと。 _DEBUG が #define されてると上の ASSERT() 
そうじゃない時は下の ASSERT() 。って、上はなんか色々入ってるのに、
下はなんかすんごくちょっとなんですけど
っていうか、つまり ASSERT(f) が ((void)0) になるわけでしょ? 
ASSERT(f) の f は?
ないね……そっか、これが ++i が消えちゃう原因?
そゆこと! つまり ASSERT() が中身もまるごと ((void)0) になっちゃ
うってこと
……ねー

void CDebugDlg::OnButton1() 
{
    ((void)0);
}

ってなんか変だけど。ただの空白ってダメなの?
そうだねー、もし ASSERT() が空白になると

    CString cStr ASSERT( 0 );

ってできちゃうんだよね
うわ変……
だから空白じゃなくて 0 にして、でもそれだけだと

    int i = ASSERT( 0 );

うわまた変……
で、代入できないように void にキャストするわけ
 void って、関数の戻り値ないときのだよね
そう、だから何にも代入できないわけ
……んー、まとめると、ようするに変なことできないようにってこと?
そういうこと。まぁちょっとしたテクニックみたいなものだけどね
なんかちょっと奥が深いかもしんない……。って話を戻して、つまり
_DEBUG ってのが #define されてるかどうかなんだよね
そうそう。実はそれ、もう見てるんだよ
見てる?
 Ver 6.07 ( No.107 ) 見て
あ、【プロジェクトの設定】で #define されてるんだ!
で、それされてるのがデバッグビルドの方。リリースビルドだと
ないね。そうなると ASSERT() まるごと消えちゃうんだ
そういうこと。たとえばリリースビルドで _DEBUG, を加えると
おおっ、今度はちゃんと 101 になった!
ちなみにデバッグモードで _DEBUG, を取り除くと
おおっ、 101 ……ってさっきと変わらないやん
ちょっと複雑な話になるけど、【プロジェクトの設定】の
【C/C++】−【コード生成】ページの【使用するランタイム ライブラリ】で
(デバッグ)って付いてるのを選んでると、無理矢理 _DEBUG が #define さ
れちゃうから。だからこれを【マルチスレッド(デバッグ)】にすると
お、今度はちゃんと 100 になった。こうすれば ASSERT() がなくなっ
ちゃうわけね
ちなみになくならないのもあるよ。さっきの ASSERT() とかがあったとこ
に VERIFY() ってあるでしょ
うんある。あ、これは ((void)(f)) に置き換わるね。 f があるから、
こっちは ++i がなくなんないんだ
だから、 ASSERT() の中が消えてほしくない場合は VERIFY() を使うって
手もあるかな。でも
でも?
僕はあんまり使わないかなぁ。 ASSERT() と VERIFY() をごちゃごちゃに
するのはね。別に無理矢理中に消えて欲しくないコード書くこともないし
前に、1行に詰め込まない方がいいって言ってたもんね
ま、便利な面もあるから使うのも悪くないけど。たとえば関数の戻り値を
ASSERT() でチェックしたい時とか
そっか、そういうとき2行にすると、戻り値を入れる変数作んなきゃいけ
ないんだね
その辺は人それぞれ、かな。あとこの系統の最後に TRACE() 
いつものおなじみの TRACE() も、デバッグの時はなくなっちゃうんだ
ただ重要なのは、 TRACE() はなくなっちゃうけど、アウトプットウィン
ドウに出力する機能がなくなっちゃうわけじゃないってこと
どゆこと?
実は TRACE() は、 API の OutputDebugString() の機能を使ってるんで
す。だから

void CDebugDlg::OnButton1() 
{
    OutputDebugString( "あうとぷっと\n" );
}

うりゃ、ホントだアウトプットに出た
で、これはリリースモードでもちゃんと出るから
ほい。あ、ホントに出た
つまり!
つまり?
デバッグビルドとかリリースビルドって言っても、こういう仕組みでなっ
てるから、たとえばリリースビルドでもある程度デバッグしたりはできるん
だよね
この OutputDebugString() とか、さっきの _DEBUG とか?
そゆこと。今はまだちょっと難しくても、こういうことを知っていれば、
あとで〈リリースビルドでデバッグしないと!〉って時でも
できるようになる?
なる!

/*
    Preview Next Story!
*/
で、それっていつのこと?
〈これっていつまで続くの?〉ネタはつまらないからやめない?
やめない。っつーか今回も長すぎでしょ
デバッグ編だけでこんなになるとはなー
なんで長くなるの?
教えたいことばかりだから
というわけで次回
< Version 6.19 デバッグウィンドウがいっぱい >
につづく!
そんなにプログラミングって大変なものなの?
……世の中って汚いよね……
答えになってなーい!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。