リリースビルドすると、実行後にウインドウが巨大化する

デバッグモードでプログラムを開発してきて、いざリリースでビルドすると問題が発生するというのはよくある話。これもまた、同じような問題。

デバッグ中は無事に動いていたのに、リリースでビルドして実行すると、ウインドウが巨大化してしまう問題が発生した。
ウインドウのサイズを変更する関数 SetWindowPos() などを使った覚えがないので、ものすごく不思議な現象だった。

よくよく確認すると、原因は、WM_GETMINMAXINFO メッセージを処理する OnGetMinMaxInfo() 関数にあることがわかった。

処理は、OnInitDialog() 中で、初期状態のウインドウサイズを取得して、OnGetMinMaxInfo() にて、そのサイズ以下に縮まらないようにすること。

デバッグモードでは、うまく動いていた(様に見えた)が、リリースモードでは、OnInitDialog() で取得したウインドウサイズが入ったCRectには、デバッグモードの時と全く異なった大きなデータが入っていて、それが原因でウインドウの初期化時の最小ウインドウサイズが巨大になってしまった。

これは、ウインドウの初期化関数OnInitDialog() が呼ばれる前に OnGetMinMaxInfo() 関数が呼ばれてしまうために起こる現象。
1回目のOnGetMinMaxInfo()の呼び出しでは、初期化前のCRectを使ってしまっていた。
デバッグモードでは、変数の初期化時(メモリ割り当て時)に、変な値で上書きしてしまう。
これは、使用しているメモリ領域と、使用していないメモリ領域を判別するためのデバッグのための機能だと思われるけど、それが原因で、リリースモードで問題を起こすことは結構よくある。
リリースモードだと、初期化されないので、どんなデータが入っているのかは実行してみないとわからない。

そこで、簡単なフラグを設定して、初期化前にはウインドウサイズを制限しないように修正したところ、問題が解消した。
void CXXXDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    dprintf("GetMinMaxInfo() called!\n");
    if(m_bInitialized)
    {
        lpMMI->ptMinTrackSize.x = _rctOriginal.Width();
        lpMMI->ptMinTrackSize.y = _rctOriginal.Height();
    }
}

デバッグモードとリリースモードでは、微妙な違いがあるので注意が必要です。

dprintf() 関数は、デバッグプリントを行うための自作関数。
(というか、実は或曰-- 2001年9月分 -- から拝借 ^^;)
void dprintf(char *format, ...)
{
    va_list vl;
    char buff[1024];
    DWORD err = GetLastError();
    {
        va_start(vl, format);
        _vsnprintf(buff, sizeof(buff), format, vl);
        va_end(vl);
        OutputDebugString(buff);
    }
    SetLastError(err);
}

リリースビルドでも、TRACE() のように、printf() の構文でデバッグウインドウにメッセージを送れるようになります。(実際にそれをやっているのはOutputDebugString()です。)

リリースビルドでデバッグ情報が出せると、現地でのデバッグとかに便利です。
ログファイルに出力すると、溜まりに貯まって肥大化したり、増えすぎたログファイルをどうするかという問題もありますし、ログファイルの切り捨てとか、保存場所とか、悩みは尽きません。
デバッグ出力だと、問題が発生したときに、ピンポイントで情報を取り出すことができますので便利です。
忙しい関数に仕掛けると、パフォーマンスに影響しますので、注意。

デバッグ情報は、開発環境の他、SysinternalsDebugView(フリーウェア)でみれます。


... 前にも同じ問題にぶち当たったっけ。。。(^^;)
ウインドウの巨大化が解決しました。
[PR]
by isoq | 2005-09-30 16:03 | C/C++/Win32
e87.com(千趣会イイハナ) 花を贈るなら日比谷花壇
<< カラスのお灸 やっと解決!VCのCL.EXE... >>