人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

(環境VC++6)下記描画処理を繰返行った時に
LoadImageでhBitmapにNULLが入る場合があります。
この場合は再度LoadImageを呼ぶようにしていますが
またhBitmapにNULLが入ってしまい、BMPが読めません。
どのような原因でこのような症状が発生するのか
教えていただきたくお願いします。

<補足>
・BMP連続描画を行うことができるが、なんらかの条件により失敗している。
(原因は不明。描画回数or描画間隔が原因かも)
・10回以上描画した後にメモリリークなし
・デバッグmodeで確認したとき問題発生後に、添付画像の警告が出た。

<ソース>
HBITMAP hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),(LPCSTR)csBmpName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
static BITMAP bmpBack;
if(hBitmap == NULL)return FALSE;
GraphicMap.Attach(hBitmap);
GetObject(hBitmap , sizeof(BITMAP) , &bmpBack);
CDC cdcSubDC;
cdcSubDC.CreateCompatibleDC(pDC);
CBitmap* oldBMP=cdcSubDC.SelectObject(&GraphicMap);
cdcMain->SetStretchBltMode(COLORONCOLOR) ;

if(0==cdcMain->StretchBlt(iXzahyou,iYzahyou,iMainYoko,iMainTate,
&cdcSubDC,iXzahyou*bmpBack.bmWidth/iMainYoko,iYzahyou*bmpBack.bmHeight/iMainTate,
iMainYoko*bmpBack.bmWidth/iMainYoko,iMainTate*bmpBack.bmHeight/iMainTate,SRCCOPY)){
iReturnValue=FALSE;
}
cdcSubDC.SelectObject(oldBMP);

1170177249
●拡大する

●質問者: harunoharuno
●カテゴリ:コンピュータ ゲーム
✍キーワード:BMP PDC VC++ デバッグ メモリリーク
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● TONTON3
●40ポイント

http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200607...

oldBMPのDeleteObject

cdcSubDCのDeleteDc

が抜けてませんか?

◎質問者からの返答

回答ありがとうございます。試してみても改善しませんでしたが

そこに問題があるのかもしれませんね。

私が用いている教科書(新VisualC++6.0入門ビギナー編)には、oldBMPや

cdcSubDCを削除するように書かれていませんでしたので

教えていただいたコードを追加する必要性について説明していただきたくよろしくお願いします。

それと、下記のように私の理解に基づきコメントを追加しました。

何か不自然なところなどありましたらご指摘いただけると嬉しいです。

よろしくお願いします。

HBITMAP hBitmap = (HBITMAP)::LoadImage(ファイル名等) //ビットマップロード

if(hBitmap == NULL)return FALSE; //ロードできなかったらReturn

GraphicMap.Attach(hBitmap); //GraphicMapとビットマップの関連付け

GetObject(hBitmap , sizeof(BITMAP) , &bmpBack);

CDC cdcSubDC; //裏画面作成

cdcSubDC.CreateCompatibleDC(pDC); //裏画面にメイン画面(pDC)との互換性を持たせる

CBitmap* oldBMP=cdcSubDC.SelectObject(&GraphicMap); //裏画面とGraphicMapの関連付け

cdcMain->SetStretchBltMode(COLORONCOLOR); //

//メイン画面に裏画面の画像を描画

if(0==cdcMain->StretchBlt(iXzahyou,iYzahyou,iMainYoko,iMainTate,

&cdcSubDC,iXzahyou*bmpBack.bmWidth/iMainYoko,iYzahyou*bmpBack.bmHeight/iMainTate,

iMainYoko*bmpBack.bmWidth/iMainYoko,iMainTate*bmpBack.bmHeight/iMainTate,SRCCOPY)){

iReturnValue=FALSE;

}

cdcSubDC.SelectObject(oldBMP); //なぜそうするのか

//理解していない参考書どおり

cdcSubDC.DeleteDC();

oldBMP->DeleteObject();


2 ● SevenS
●50ポイント ベストアンサー

読み込まれたhBitmapは、StretchBltの後再利用されていないので、DeleteObjectで削除すべきではないでしょうか?

頭にHのつくハンドルと呼ばれるものはWindowsサイドで管理しているものなので、メモリリークとしては現れなかったような気もします。

念のため、LoadImageの結果がNULLのとき、GetLastErrorを取得することをオススメします(FormatMessageと併用するとなおGood)。

もしかすると解決の糸口が見つかるかもしれません。

それと、お節介かも知れませんがいくつか。

  1. cdcSubDC.CreateCompatibleDCの引数は、pDCではなくcdcMainがふさわしいのでは?
  2. 読み込みは、HBITMAP LoadBitmap( LPCTSTR lpszFileName )のような関数に処理をまとめた方が楽

ただ、この部分の処理は重いので、OnPaintなどには使わない方がいいかもしれませんね。

備考: VC++7.0以降なら、MFCのCImageクラスを使って、

LPCTSTR lpszFileName = TEXT( "bitmap.bmp" );
CImage image;
image.Load( lpszFileName );
image.StretchBlt(
 cdcMain->GetSafeDC(),
 iXzahyou, iYzahyou,
 iMainYoko, iMainTate,
 iXzahyou * image.GetWidth() / iMainYoko,
 iYzahyou * image.GetHeight() / iMainTate,
 image.GetWidth(), image.GetHeight() );

とできるようです。

http://www.geocities.jp/chiakifujimon/makesoft2/proc4.html

◎質問者からの返答

いろいろと、教えていただきありがとうございます。

GetLastErrorとFormatMessageを併用したところ

『このコマンドを実行するのに十分な記憶域がありません』とでていました。

やはり、ご指摘いただいているhbitmap等のリソース開放処理がないためかな?

>>cdcSubDC.CreateCompatibleDCの引数は、pDCではなくcdcMainがふさわしいのでは?

pDCはcdcMainのアドレスが入っているので、cdcMainと同じです。

>>読み込みは、HBITMAP LoadBitmap( LPCTSTR lpszFileName )のような関数に

>>処理をまとめた方が楽

確かにそうしたほうがソースも読みやすいですね。

コーディングに対する指摘も参考になり大変ありがたいです。

他にまた気になる点などありましたらまた、ご指摘いただきたくよろしくお願いします。


>>頭にHのつくハンドルと呼ばれるものはWindowsサイドで管理しているものなので、メモリリークとしては現れなかったような気もします。

あれっっ

ひょっとしてHICONなども開放する必要がありますか?


3 ● SevenS
●50ポイント

自信はありませんが…

HICONがプログラムモジュール内のリソースをロードするだけなら、リリースする必要はないと思います。

無論、ハンドルやポインタは、ちゃんと解放する癖をつけておくのは正しいことだと思います。

http://support.microsoft.com/kb/87976/ja

◎質問者からの返答

回答ありがとうございます。

WindowsタスクマネージャのPF使用量を見ながら

メモリリークしている処理を探したのですが、

SHGetFileInfo関数でHICONを受け取るときに

PF使用量が増加していることがわかりました。

そこでネットで検索したDestroyIcon関数の

開放処理を追加したところ、

SHGetFileInfo関数を呼び出すごとに

増加していたPF使用量が増加しなくなり、

BMP描画関数でこけることもなくなりました!!

裏づけが信頼性の高い資料などで確認取れていませんが、

SHGetFileInfo関数で取得した

HICONをDestroyIcon関数で

開放していなかったため、アイコンを再描画するたびに

メモリリークが発生し、

その影響からBMPファイル読み込みに支障がでたようです。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ