DeleteObject()やDeleteDC()の呼び出しが必要な場合

解決


うーん  2007-11-29 19:40:00  No: 67036  IP: [192.*.*.*]

お世話になります.あるサイトを参考にメモリDCの勉強をしているのですが,DeleteObject()やDeleteDC()の呼び出しがどういう場合に必要なのか
わかりません。MSDNを見てもどういう場合に呼び出しが必要か明確に書いて
ないようです。

質問したいことは、下記のコードに関する以下の点です。

(1) 参考にしたサイトによると、①でビットマップオブジェクトをnewして
②のpBMP->DeleteObject()でビットマップオブジェクトを解放すると
あったのですが、解放は③のdelete pBMPで行なうべきではないで
しょうか?

(2) CBitmapオブジェクトのデストラクタの中にはDeleteObject()が記述され
ているのでしょうか?記述されているのならDeleteObject()の呼び出しは必要
ないように思うのですが。それとも、CreateCompatibleBitmap()を呼び出した
場合には必ずDeleteobject()を呼び出すことになっているのでしょうか?

(3) ④のDeleteDC()もデストラクタ中に記述されているなら呼び出す必要
がないと思いますが。 

環境はVC++2005、MFCです。よろしくお願い致します。


void CmdcView::OnDraw(CDC* pDC)
{
       ...
      CDC mDC;
      mDC.CreateCompatibleDC(pDC);

      CBitmap *pBMP, *pOldBMP;
      pBMP=new CBitmap;                  //  ①    
      pBMP->CreateCompatibleBitmap(pDC, 256, 128);  
      pOldBMP=mDC.SelectObject(pBMP);

      mDC.FillSolidRect(0,0,256,128,RGB(255,0,0));
      pDC->BitBlt(100,100,256,128,&mDC,0,0,SRCCOPY);
      
      mDC.SelectObject(pOldBMP);
      pBMP->DeleteObject();              //  ②
      delete pBMP;                       //  ③

      mDC.DeleteDC()                     //  ④
}

編集    削除
うーん  2007-11-29 19:42:52  No: 67037  IP: [192.*.*.*]

すみません。ダブってしまいました。

編集    削除
うーん  2007-11-29 21:30:24  No: 67038  IP: [192.*.*.*]

自己レスです。

>(2) CreateCompatibleBitmap()を呼び出した
>場合には必ずDeleteobject()を呼び出すことになっているのでしょうか?

これはMSDNのCreateCompatibleBitmap()の説明のところに記載されてました。

>(3) ④のDeleteDC()もデストラクタ中に記述されているなら呼び出す必要
>がないと思いますが。

すみません。これもMSDNに「一般的には、この関数を呼び出さずに、デスト
ラクタを使います。」と記載されてました。

(1)についてもdelete pBMP; が必要だが、その前にpBMP->DeleteObject();
を呼び出す必要がある、と理解することにしました。勘違いでしたらご指摘
願います。

編集    削除
maru  2007-11-29 21:39:48  No: 67039  IP: [192.*.*.*]

> (1) 参考にしたサイトによると、①でビットマップオブジェクトをnewして
> ②のpBMP->DeleteObject()でビットマップオブジェクトを解放すると
> あったのですが、解放は③のdelete pBMPで行なうべきではないで
> しょうか?
①のnewと③のdeleteが対になっているのは正しいのですが、②の
DeleteObject()は、①の直後のCreateCompatibleBitmapに対応しています。 
MFCのCBitmap::CreateCompatibleBitmapの説明には明示的には書いてありま
せんがグローバルのCreateCompatibleBitmapの説明には不用になったら DeleteObjectしろ、と"英語"で書いてあります。

> (2) CBitmapオブジェクトのデストラクタの中にはDeleteObject()が記述され
> ているのでしょうか?
記述されていないと思います。

> 記述されているのならDeleteObject()の呼び出しは必要
> ないように思うのですが。それとも、CreateCompatibleBitmap()を呼び出した
> 場合には必ずDeleteobject()を呼び出すことになっているのでしょうか?
CBitmapオブジェクトの寿命とCreateCompatibleBitmap-DeleteObject間の寿命
が異なり、DeleteObject()を行なわないと「非常に貴重」なWindowsのリソース
をくってしまうため、明示的にDeleteObject()を呼び出すことになっています。

> (3) ④のDeleteDC()もデストラクタ中に記述されているなら呼び出す必要
> がないと思いますが。 
上述したのと同じ理由です。

# MFCはWindows APIの非常に薄いラッパーなので、デストラクタで後始末可
# 能と思われる処理も明示的に行なう必要が多々あります。

編集    削除
maru  2007-11-29 21:48:51  No: 67040  IP: [192.*.*.*]

> すみません。これもMSDNに「一般的には、この関数を呼び出さずに、デスト
> ラクタを使います。」と記載されてました。
こんなこと書いてありましたぁ?

私が見ているヘルプのCDC::DeleteDCには
「DeleteDC 関数は、一般的に CreateDC、CreateIC、CreateCompatibleDC で
作成されたデバイス コンテキストの削除に使います。」
って書いてあるんですけど。

編集    削除
うーん  2007-11-29 21:49:03  No: 67041  IP: [192.*.*.*]

maruさん、レスありがとうございます。

>CBitmapオブジェクトの寿命とCreateCompatibleBitmap-DeleteObject間
>の寿命が異なり、DeleteObject()を行なわないと「非常に貴重」な
>Windowsのリソースをくってしまうため、明示的にDeleteObject()を呼び
>出すことになっています。

># MFCはWindows APIの非常に薄いラッパーなので、デストラクタで後始末可
># 能と思われる処理も明示的に行なう必要が多々あります。

デストラクタに記述すればいいのに何でわざわざ別に呼び出す必要があるん
だろ?とひっかかっていましたが、おかげですっきりしました。
どうもありがとうございました。

編集    削除
gak  2007-11-29 23:29:58  No: 67042  IP: [192.*.*.*]

> (1)についてもdelete pBMP; が必要だが、その前にpBMP->DeleteObject();
> を呼び出す必要がある、と理解することにしました。勘違いでしたらご指摘
> 願います。
イヤイヤ.
CBitmap の基本クラス CGdiObject のデストラクタで DeleteObject() されてるハズですよ

明示的に DeleteObject() を呼ばないといけないのなら
いままで俺が組んできたMFCプログラムは全滅だ。
このやりとりを見てちょっと焦ったよ…

編集    削除
maru  2007-11-30 01:14:51  No: 67043  IP: [192.*.*.*]

> イヤイヤ.
> CBitmap の基本クラス CGdiObject のデストラクタで DeleteObject() されてるハズですよ
そうでしたか。失礼しました。

編集    削除
うーん  2007-11-30 05:49:20  No: 67044  IP: [192.*.*.*]

返事が遅れてすみません。

maruさん

>こんなこと書いてありましたぁ?

http://msdn2.microsoft.com/ja-jp/library/40y7h98e(vs.80).aspx

を参照しました。

gakさん

>CBitmap の基本クラス CGdiObject のデストラクタで DeleteObject() され
>てるハズですよ

そうですか・・・あちこちの掲示板や本のプログラム例を見ると、DeletObject()
があるものと無いものがあって一体どっちが正しいのか?と混乱しています。

ともかく、maruさん、gakさん、ありがとうございました。

編集    削除
maru  2007-11-30 18:10:58  No: 67045  IP: [192.*.*.*]

> >こんなこと書いてありましたぁ?
> http://msdn2.microsoft.com/ja-jp/library/40y7h98e(vs.80).aspx
> を参照しました。
確認しました。確かにかいてありますね...

> そうですか・・・あちこちの掲示板や本のプログラム例を見ると、DeletObject()
> があるものと無いものがあって一体どっちが正しいのか?と混乱しています。
DeletObject()が書いてあるプログラムは、私と同じで、「Windows APIでプロ
グラムを書いてたことがあり、その頃はDeletObject()を書く必要があったので
MFCでも必要と勘違いしている」のではないかと思います。
MFCでは、オブジェクトの寿命とそのオブジェクトが管理しているリソース(資
源)の寿命が異なるものがあり、確かに分かりにくい所ではあると思います。

編集    削除