デバイスコンテキストの解放で異常終了します。 – プログラミング – Home

デバイスコンテキストの解放で異常終了し...
 
通知
すべてクリア

[解決済] デバイスコンテキストの解放で異常終了します。


SOS
 SOS
(@SOS)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

はじめまして。
ちょっと困ってて皆さんのお力添えを拝借したいのでよろしくお願いします。

以下、二種類の方法でデバイスコンテキストを構築しています。
その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();
}


引用未解決
トピックタグ
SOS
 SOS
(@SOS)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

以下のように変更したら、うまくいきました。
SelectObjectは、引数と戻り値の型は一致させないとダメみたいですね。

CBitmap *OldView;

HBITMAP *OldView;

OldWork = (CBitmap*)DcWork.SelectObject(WorkBMP);

OldWork = (HBITMAP*)DcWork.SelectObject(WorkBMP);

また、「DcWork.DeleteDC();」の前に、「DeleteObject(WorkBMP);」もやったほうがいい
みたいですね。

でもなぜSelectObjectで復帰させる必要があるのか?復帰させないとどうなるのか?
「DeleteObject(WorkBMP);」をやらないとどうなるのか?
その辺のところが、よく分かりません。
「DcWork.DeleteDC();」だけで、問題ないんじゃないでしょうか?


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

これが参考になるかもしれません
http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

>SelectObjectは、引数と戻り値の型は一致させないとダメみたいですね。

 まずHBITMAPとCBitmapを混同しているっぽいですが、全くの別物であることを確認して
ください。

>でもなぜSelectObjectで復帰させる必要があるのか?復帰させないとどうなるのか?

 必須です。
 戻さないと、適切に開放できません。

>「DeleteObject(WorkBMP);」をやらないとどうなるのか?

 GDIリソースを食いつぶします。
 GDIリソースの数は有限です。
 OSが不明ですが、Windows7などのタスクマネージャではGDIハンドルの数が表示するこ
とができるので、その推移を観察してみるとアプリが死ぬタイミングなども分かると思い
ます。


返信引用
SOS
 SOS
(@SOS)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

ロマさん、ありがとうございます。でもリンク先、英語なんですね………orz

ARさん、解放せずにプログラムを終了しても、食いつぶしたままですか?
もしそうだとすれば、起動と終了を繰り返すたびにリソースが消費されていく………って
ことですね。
ちゃんとリソースを解放してるかどうかって、なんとか調べる方法ってありますか?


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

>ARさん、解放せずにプログラムを終了しても、食いつぶしたままですか?
>もしそうだとすれば、起動と終了を繰り返すたびにリソースが消費されていく………って
>ことですね。

 アプリケーション終了時には開放されます。
 ただし、Windowsの描画全般にも影響を及ぼす致命的な不具合なので、適切に処置すべ
きです。

>ちゃんとリソースを解放してるかどうかって、なんとか調べる方法ってありますか?

 タスクマネージャを見るように回答したつもりですが・・・。
 表示名はGDIオブジェクトですね。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>タスクマネージャを見るように回答したつもりですが・・・。
>表示名はGDIオブジェクトですね。

>開発環境はVisualStudio2005です。
windowsXPの可能性がありますね。
表示→列の選択→GDIオブジェクトで見れそうですね。


返信引用
SOS
 SOS
(@SOS)
ゲスト
結合: 12年前
投稿: 4
Topic starter  

みなさんのおかげで、いろいろ疑問が解けました。ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました