Platform SDK: DirectX |
ここでは、C++ でのアプリケーション開発について説明する。
DirectDraw プログラミングで使うすべてのオブジェクト (DirectDraw オブジェクト、サーフェス パレット、クリッパーなど) は、アプリケーションのような他のオブジェクトがそれを必要とするかぎり、メモリ内に存在するだけである。オブジェクトの有効期間とは、オブジェクトがメモリに作成されて配置された瞬間から、オブジェクトが解放された後にメモリから削除されるまでの時間である。すべての DirectX コンポーネントに従うコンポーネント オブジェクト モデル (COM) では、1 つのオブジェクトがサービスを必要とする他のオブジェクトの数を調査し続けることを指示する。この数は参照カウントと呼ばれ、オブジェクトの有効期間を決定する。また、COM では、IUnknown::AddRef および IUnknown::Release メソッドを使ってオブジェクトを調べ、アプリケーションが参照カウントを明示的に管理することができる。COM の規則に従い、これらのメソッドを使って確認すること。
オブジェクトに対する参照カウントを管理するには、誰もが IUnknown メソッドを使用できる。また、DirectDraw オブジェクトは内部で参照カウントを使う。IDirectDraw7 (IDirectDraw2 や IDirectDraw と対照に) インターフェイスを使って、サーフェスのような "子" オブジェクトを作成する場合、子は "親" の DirectDraw オブジェクトの IUnknown::AddRef メソッドを使用して、親の参照カウントをインクリメントする。
アプリケーションでオブジェクトが必要なくなると、参照カウントをデクリメントする Release メソッドを呼び出す。参照カウントがゼロになると、そのオブジェクトはメモリから削除される。子オブジェクトの参照カウントがゼロになると、親の IUnknown::Release メソッドを呼び出して、親のサービスを必要とするオブジェクトが少なくとも 1 つあることを示す。
IDirectDraw7::CreateSurface の呼び出しで作成するフリッピング チェーンのバックバッファ サーフェスのように暗に割り当てられたオブジェクトでは、そのオブジェクトの親の DirectDrawSurface オブジェクトが解放されると、自動的に割り当てが削除される。また、アプリケーション ウィンドウを作成するスレッドから、DirectDraw オブジェクトだけを解放できる。単一のスレッド化されたアプリケーションに対して、この制限は 1 つのスレッドだけが存在するように明らかに適用されない。アプリケーションで、アタッチ状態の DirectDrawClipper オブジェクトを使用する 2 つのサーフェス (CreateSurface の呼び出しで作成された) のプライマリ フリッピング チェーンを作成した場合、これらのオブジェクトを確実に解放するコードは以下のようになる。
// この例では、g_lpDDraw、g_lpDDSurface、および // g_lpDDClip がオブジェクトに対する有効なポインタとなる。 void ReleaseDDrawObjects(void) { // DirectDraw オブジェクト ポインタが有効な場合、 // そのオブジェクトとポインタは安全に解放される。 if(g_lpDDraw) { // DirectDraw オブジェクトを解放する (子が IDirectDraw2 // や IDirectDraw から作成された場合、この呼び出しは // 安全とはならない。この場合の詳細情報は、 // 以下に示すメモを参照すること)。 g_lpDDraw->Release(), g_lpDDraw = NULL; // ここでは、サーフェスに割り当てられるクリッパーを解放する if(g_lpDDClip) g_lpDDClip->Release(), g_lpDDClip = NULL; // ここでは、プライマリ フリッピング チェーンを解放する。フリッピングチェーン サーフェスが // CreateSurface の呼び出しで作成されたために、 // これは唯一有効となることに // 注意する。そのサーフェスが明示的に作成されて // アタッチされるならば、解放も明示的に // されなくてはならない。 if(g_lpDDSurface) g_lpDDSurface->Release(), g_lpDDSurface = NULL; } }
注 : DirectDraw インターフェイスの以前のバージョン (正確には、IDirectDraw2 と IDirectDraw) は、大部分の最新のインターフェイスとは異なる動作をする。以前のインターフェイスを使用している場合、親自体が解放されると、DirectDraw は自動的にすべての子オブジェクトを解放する。そのため、これらの古いインターフェイスを使用する場合は、オブジェクトを解放する順序が重要になる。この場合、DirectDraw オブジェクト自体を解放する (または、クリーンアップする親により、そのオブジェクトすべてを解放しない) 前に、DirectDraw オブジェクトの子を解放しなくてはならない。DirectDraw オブジェクトは子オブジェクトを解放するので、子を解放する前に親を解放してしまうと、親オブジェクトが子オブジェクトを解放したときに無効となったポインタが参照できなくなり、メモリに障害を受けやすくなる。
オブジェクトが必要なくなると、古いアプリケーションは子オブジェクトの自動解放に頼り、いくつかのオブジェクトを正しく解放できなくなる場合がある。この場合、この習慣があらゆる悪影響を引き起こす訳ではないが、IDirectDraw7 インターフェイスを使うときはメモリ リークの原因となることがある。