VCでJPEG画像を表示しています。
サンプルソースを沢山見ているのですが、以下の不安があります。
1.CPictureHolderをnewして得られたポインタ(m_pPicture)は、
deleteしなくて良いのでしょうか?
ちなみに今はdeleteする必要があると思ってデストラクタで
m_pPictureをdeleteしています。
2.CBitmapをnewして得られたポインタ(m_pBitmap)は、
deleteすると、アプリケーションエラーがでてしまいます。
今は、deleteしないようにしていますが、問題ないのでしょうか?
開発環境は、VC++6.0、Windows2000です。
--------------以下、ソースです。--------------
LPDISPATCH pDisp = NULL;
COleVariant varName(lpPath);
// JPEGファイルの読み込み
long Status = OleLoadPictureFile(varName, &pDisp);
if ( Status >= 0 )
{
if( m_pPicture != NULL )
{
delete m_pPicture;
m_pPicture = NULL;
}
// ディスパッチ
m_pPicture = new CPictureHolder;
m_pPicture->SetPictureDispatch((LPPICTUREDISP)pDisp);
m_hBitmap = GetBitmap();
if (m_hBitmap != NULL)
{
if( m_pBitmap != NULL )
{
delete m_pBitmap;
m_pBitmap = NULL;
}
// ビットマップの取得
m_pBitmap = new CBitmap;
m_pBitmap = CBitmap::FromHandle(m_hBitmap);
m_bDsp = true;
}
}
// 開放
if( pDisp != NULL )
{
pDisp->Release();
}
//-----デストラクタ----------------------
if( m_pPicture != NULL )
{
delete m_pPicture;
m_pPicture = NULL;
}
if( m_hBitmap != NULL )
{
DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
if( m_pBitmap != NULL )
{
delete m_pBitmap;
m_pBitmap = NULL;
}
CPictureHolderなるものを使ったことがないので確信はありませんが、
ヘルプを見る限りでは特に特殊な扱いをするものではないようですので、
newしたらdeleteが必要でしょう。
CBitmapのほうは
> m_pBitmap = new CBitmap;
> m_pBitmap = CBitmap::FromHandle(m_hBitmap);
これが原因でしょう
せっかくnewで取得したポインタをFromHandle()で上書きしてしまっています。
そもそもFromHandle()で取得したポインタは保存してはいけません。
ヘルプにもその辺の注意が書かれています。
これのせいで、newで確保したポインタはどこにも保存されなくなって迷子になり、
FromHandle()で得たポインタはアイドル時に削除されるため無効なポインタになり、
結果としてdeleteで無効なポインタを削除しようとするために落ちるのでしょう。
やるならばnewした後にAttachするとかでしょうか。
もちろん不要になったときのdeleteは必要です。
もし必要ならDetachとかも。
ちなみにちょっと気になったんですが、
> CPictureHolderをnewして得られたポインタ(m_pPicture)は、
> deleteしなくて良いのでしょうか?
というのはどこかのサンプルがそうなっていたとかですか?
お返事ありがとうございます。
>せっかくnewで取得したポインタをFromHandle()で上書きしてしまっています。
>そもそもFromHandle()で取得したポインタは保存してはいけません。
>ヘルプにもその辺の注意が書かれています。
>
>これのせいで、newで確保したポインタはどこにも保存されなくなって迷子になり、
>FromHandle()で得たポインタはアイドル時に削除されるため無効なポインタになり、
>結果としてdeleteで無効なポインタを削除しようとするために落ちるのでしょう。
ここは、私がサンプルを修正していたのが原因です。
サンプルでは、上書きしていませんでした。
さっそく試してみます。
>> CPictureHolderをnewして得られたポインタ(m_pPicture)は、
>> deleteしなくて良いのでしょうか?
>
>というのはどこかのサンプルがそうなっていたとかですか?
そうです。プロジェクトファイルごと入っているソース(cpp,h)で
そうなっていました。
CPictureHolderをnewしたものをdeleteしていませんでした。
このような感じになっていました。
この関数ってもしかして、ドキュメントをクローズしたときに
コールされるのですか?
void CXXXDoc::DeleteContents()
{
delete m_pPicture;
m_pPicture = NULL;
CDocument::DeleteContents();
}
> そうなっていました。
> CPictureHolderをnewしたものをdeleteしていませんでした。
> void CXXXDoc::DeleteContents()
> {
> delete m_pPicture;
> m_pPicture = NULL;
> CDocument::DeleteContents();
> }
矛盾していませんか?
思いっきりdeleteしてます。
> この関数ってもしかして、ドキュメントをクローズしたときに
> コールされるのですか?
疑問に思ったらまずヘルプに目を通しましょう。
> [CDocument::DeleteContents]
> (・・・略・・・)
> ドキュメントが破棄される直前に呼び出されます。
> またドキュメントを再使用する前に、
> ドキュメントが空であることを確認するために呼び出されます。
> (・・・略・・・)
と、疑問の答えがそのまま書かれています。
他にもOnCloseDocument、OnNewDocument、OnOpenDocumentなどにも目を通せば
どのようなタイミングでDeleteContentsが呼ばれるか把握するヒントになるでしょう。
それと少し話は変わるのですが、メンバ変数にm_hBitmapとm_pBitmapを
両方持っているようですが、これは両方ないと困る理由があるのでしょうか?
特に理由がないのならm_pBitmapひとつに絞ったほうがいろいろと面倒がなくて
いいと思います。
憂さん、ありがとうございました。
やはり、deleteしていたのですね。
ドキュメントをクローズしたときに
DeleteContents()がコールされていました。
あと、メンバ変数は、m_pBitmap1つになるよう考え直します。
ありがとうございました。