はじめまして。
ちょっと困ってて皆さんのお力添えを拝借したいのでよろしくお願いします。
以下、二種類の方法でデバイスコンテキストを構築しています。
その1の方法は正常に動作するのですが、
その2の方法は解放時に以下の異常終了が発生しちゃいます。
> Test.exe の 0x7822409b (mfc80d.dll) でハンドルされていない例外が発生しました:
> 0xC0000005: 場所 0x01850013 を読み込み中にアクセス違反が発生しました。
下記ソースコードの「DcWork.SelectObject(OldWork);」の行で異常終了するようです。
ごらんのように、解放時の処理は、その1とまったく同じです。
CreateDIBSectionで構築する場合はなにか特別なことをしないとならないのかと思うので
すが、何が足りないのかよくわからずにいます。
開発環境はVisualStudio2005です。
void Func(CDC* DC, HWND myHwnd)
{
// デバイスコンテキスト構築その1(うまくいく)
CDC DcView;
CBitmap *OldView;
CBitmap BmpView;
DcView.CreateCompatibleDC(DC);
BmpView.CreateCompatibleBitmap(DC,256,256);
OldView = DcView.SelectObject(&BmpView);
DcView.SelectObject(OldView);
DcView.DeleteDC();
// デバイスコンテキスト構築その2(解放時に異常終了)
CDC DcWork;
CBitmap *OldWork;
BITMAPINFO biBMP;
HBITMAP WorkBMP;
LPBYTE WorkPix;
ZeroMemory(&biBMP, sizeof(biBMP));
biBMP.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
biBMP.bmiHeader.biBitCount = 24;
biBMP.bmiHeader.biPlanes = 1;
biBMP.bmiHeader.biWidth = 256;
biBMP.bmiHeader.biHeight = -256;
WorkBMP = CreateDIBSection(NULL, &biBMP, DIB_RGB_COLORS, (void **)
(&WorkPix), NULL, 0);
DcWork.CreateCompatibleDC(DC);
OldWork = (CBitmap*)DcWork.SelectObject(WorkBMP);
DcWork.SelectObject(OldWork); ←ここで異常終了
DcWork.DeleteDC();
}
以下のように変更したら、うまくいきました。
SelectObjectは、引数と戻り値の型は一致させないとダメみたいですね。
CBitmap *OldView;
↓
HBITMAP *OldView;
OldWork = (CBitmap*)DcWork.SelectObject(WorkBMP);
↓
OldWork = (HBITMAP*)DcWork.SelectObject(WorkBMP);
また、「DcWork.DeleteDC();」の前に、「DeleteObject(WorkBMP);」もやったほうがいい
みたいですね。
でもなぜSelectObjectで復帰させる必要があるのか?復帰させないとどうなるのか?
「DeleteObject(WorkBMP);」をやらないとどうなるのか?
その辺のところが、よく分かりません。
「DcWork.DeleteDC();」だけで、問題ないんじゃないでしょうか?
>SelectObjectは、引数と戻り値の型は一致させないとダメみたいですね。
まずHBITMAPとCBitmapを混同しているっぽいですが、全くの別物であることを確認して
ください。
>でもなぜSelectObjectで復帰させる必要があるのか?復帰させないとどうなるのか?
必須です。
戻さないと、適切に開放できません。
>「DeleteObject(WorkBMP);」をやらないとどうなるのか?
GDIリソースを食いつぶします。
GDIリソースの数は有限です。
OSが不明ですが、Windows7などのタスクマネージャではGDIハンドルの数が表示するこ
とができるので、その推移を観察してみるとアプリが死ぬタイミングなども分かると思い
ます。
ロマさん、ありがとうございます。でもリンク先、英語なんですね………orz
ARさん、解放せずにプログラムを終了しても、食いつぶしたままですか?
もしそうだとすれば、起動と終了を繰り返すたびにリソースが消費されていく………って
ことですね。
ちゃんとリソースを解放してるかどうかって、なんとか調べる方法ってありますか?
>ARさん、解放せずにプログラムを終了しても、食いつぶしたままですか?
>もしそうだとすれば、起動と終了を繰り返すたびにリソースが消費されていく………って
>ことですね。
アプリケーション終了時には開放されます。
ただし、Windowsの描画全般にも影響を及ぼす致命的な不具合なので、適切に処置すべ
きです。
>ちゃんとリソースを解放してるかどうかって、なんとか調べる方法ってありますか?
タスクマネージャを見るように回答したつもりですが・・・。
表示名はGDIオブジェクトですね。
>タスクマネージャを見るように回答したつもりですが・・・。
>表示名はGDIオブジェクトですね。
>開発環境はVisualStudio2005です。
windowsXPの可能性がありますね。
表示→列の選択→GDIオブジェクトで見れそうですね。
みなさんのおかげで、いろいろ疑問が解けました。ありがとうございました。