Parent and Child Object Lifetimes
A version of this page is also available for
4/8/2010
All objects you will use in DirectDraw programming — the DirectDraw object, surfaces, palettes, clippers, and such — only exist in memory for as long as another object, such as an application, needs them.
The time that passes from the moment when an object is created and placed in memory to when it is released and subsequently removed from memory is known as the object's lifetime.
The Component Object Model (COM) followed by all DirectX technologies dictate that an object must keep track of how many other objects require its services.
This number, known as a reference count, determines the object's lifetime. COM also dictates that an object expose the IUnknown::AddRef and IUnknown::Release methods to enable applications to explicitly manage its reference count; make sure you use these methods in accordance to COM rules.
You are not the only one who is using the IUnknown methods to manage reference counts for objects — DirectDraw objects use them internally, too.
When you use the IDirectDraw interface to create a child object like a surface, the child uses the IUnknown::AddRef method of the parent DirectDraw object to increment the parent's reference count.
When your application no longer needs an object, call the Release method to decrement its reference count. When the count reaches zero, the object is removed from memory.
When a child object's reference count reaches zero, it calls the parent's IUnknown::Release method to indicate that there is one less object who will be needing the parent's services.
Implicitly allocated objects, such as the back-buffer surfaces in a flipping chain that you create with a single IDirectDraw::CreateSurface call, are automatically deallocated when their parent DirectDrawSurface object is released.
Also, you can only release a DirectDraw object from the thread that created the application window. For single-threaded applications, this restriction obviously does not apply, as there is only one thread.
Code Example
Consider an application that creates a primary flipping chain of two surfaces (created by a single CreateSurface call) using one of the attached Independent DirectDrawClipper Objects. The following code example demonstrates a safer way to release these objects.
Note
To make the following code example easier to read, security checking and error handling are not included. This code example should not be used in a release configuration unless it has been modified to include them.
// For this example, the g_lpDDraw, g_lpDDSurface, and
// g_lpDDClip are valid pointers to objects.
void ReleaseDDrawObjects(void)
{
// If the DirectDraw object pointer is valid,
// release it and the objects it owns.
if(g_lpDDraw)
{
// Release the DirectDraw object. (This call would not
// be safe if the children were created through IDirectDraw2
// or IDirectDraw. See the following note for
// more information)
g_lpDDraw->Release(), g_lpDDraw = NULL;
// Now, release the clipper that is attached to the surfaces.
if(g_lpDDClip)
g_lpDDClip->Release(), g_lpDDClip = NULL;
// Now, release the primary flipping chain. Note
// that this is only valid because the flipping
// chain surfaces were created with a single
// CreateSurface call. If they were explicitly
// created and attached, then they must also be
// explicitly released.
if(g_lpDDSurface)
g_lpDDSurface->Release(), g_lpDDSurface = NULL;
}
}
Note
Earlier versions of the DirectDraw interface behave differently than the most recent interface.
Note
When using these early interfaces, DirectDraw automatically releases all child objects when the parent itself is released. As a result, if you use these older interfaces, the order in which you release objects is critical.
Note
In this case, you should release the children of a DirectDraw object before releasing the DirectDraw object itself (or not release them at all, counting on the parent to do cleanup for you).
Note
Because the DirectDraw object releases the child objects, if you release the parent before the children, you are very likely to incur a memory fault for attempting to dereference a pointer that was invalidated when the parent object released its children.
Note
Some older applications relied on the automatic release of child objects and neglected to properly release some objects when no longer needed.
Note
At the time, this practice did not cause any negative side effects, however doing so when using the IDirectDraw interface might result in memory leaks.