ページ 11

WINAPIについての質問です

Posted: 2013年5月24日(金) 01:43
by びぎなぁ

コード:

HDC CreateEmptyBMP(HDC hdc, int width, int height){
    HBITMAP hbmp;
    HDC hdc_work;

    hbmp = CreateCompatibleBitmap(hdc, width, height);
    hdc_work = CreateCompatibleDC(hdc);
    SelectObject(hdc_work, hbmp);
    PatBlt(hdc_work, 0, 0, width, height, WHITENESS); // 白で塗りつぶす
    DeleteObject(hbmp);
    return hdc_work;
}
メインループ内で(~はその他最低限必要なものが記述されていると思ってください、変数宣言、メッセージ処理など)

コード:

int WINAPI WinMain(~){
    //変数宣言
    ~
    HDC hDC_Test;
    ~
    while(1){
        ~
        hDC_Test = CreateEmptyBMP(~);
    }
    return 0;
}
このように何度も呼び出した場合、上の関数のhdc_workは自動解放されますか?

某所でも質問したのですが、あまりにも酷いコードと言われるだけで、なんの建設的な回答すら得られなかったので
具体的にどのあたりが悪いコードなのかもご教授いただければ嬉しいです。

Re: WINAPIについての質問です

Posted: 2013年5月24日(金) 02:23
by YuO
WindowsのGDIオブジェクトやカーネルオブジェクトは,プロセス終了時まで自動的に解放されることはありません。
そもそも,ハンドルが使われていないことをWindowsが検知することは不可能ですから。

さらに,選択された状態のGDIオブジェクトをDeleteObjectすることはできません。
DeleteObject functionのReturn Valueの所にも,
「成功すれば非0を,ハンドルが無効かDCに選択されていれば0を返す」という書き方で,DCに選択されているオブジェクトをDeleteObjectできないことが書かれています。

どちらもリソースリークなので,いつかCreateCompatibleBitmapやCreateCompatibleDCで失敗します。

Re: WINAPIについての質問です

Posted: 2013年5月24日(金) 03:04
by びぎなぁ
なるほど。やはりリークしてるんですね。

解放系はすべてif文で返却値を確認したほうがよさそうかな。
少し自分で調べて改良してみます。

ありがとうございました。

Re: WINAPIについての質問です

Posted: 2013年5月24日(金) 17:11
by ISLe
CreateCompatibleDCで作成したデバイスコンテキストはDeleteDCを使って削除します。
自動的には削除されません。

あらかじめDeletObjectしておけば、デバイスコンテキストの消滅に合わせてビットマップも消滅すると考えたのでしょうが、ビットマップオブジェクトにスマートポインタのような機能はありません。
そもそもビットマップオブジェクトは複数のデバイスコンテキストに選択することはできないので、特定のデバイスコンテキストと結び付けてしまうとデバイスの変化に対応できません。

描画する直前に描画対象と互換性のあるデバイスコンテキストを作成、ビットマップを選択、描画、描画後にビットマップを選択解除、速やかに互換性のあるデバイスコンテキストを削除、とするのが一般的です。

デスクトップ画面に描画するだけだからといって、プログラム起動時に作成したデスクトップ画面と互換性のあるデバイスコンテキストがプログラム終了時まで互換性を維持できるとも限りません。提示されたようなコードだとプログラム実行中にふいに画面の描画が無くなる可能性が無きにしもあらずです。