处理COM对象的寿命
当对象创建的时候, 系统分配需要的内存资源。当对象不再需要的时候,对象应该被销毁,以便系统将该内存资源用于其他的目的。在C++中,你可以通过new和delete直接控制其对象的存在寿命。但是COM对象却不能直接被创建或销毁。原因是多个应用程序可能同时使用同一个COM对象。假如其中的一个应用程序撤销了COM对象,那么使用这个COM对象的其他应用程序就可能运行失败。系统使用引用计数来控制COM对象的存在寿命。
对象的引用计数是用来标识接口被申请了几次的一个数字。接口被申请一次,使用计数便会增加1。当应用程序不再需要这个接口并且释放它的时候,引用计数就会减1。如果引用计数大于0,这个COM对象就继续存在内存中。当引用计数达到0的时候,这个对象就会自己销毁,你不需要知道关于这个COM对象的引用计数的任何事情。你只需得到或释放一个适当的接口,对象会自己判断它的存在寿命。
注释:在COM应用程序中,适当的处理引用计数是至关重要的,不然很容易出现内存泄漏。COM程序员最常犯得一个错误是没有释放一个接口。当这种情况发生的时候,引用计数将永远不会达到0,这样COM对象将永远在内存中存在。
引用计数的增1和减1
任何时候你得到一个新的接口指针,引用计数都会通过呼叫IUnkown::AddRef来增加引用计数,但是你的应用程序通常不需要呼叫这个方法。假如你是通过创建一个对象来得到一个接口指针,也或者是通过IUnknown::QueryInterface得到的,对象将会自动的增加引用计数。但是,假如你是通过其他的方法得到接口指针的,比如:拷贝一个已经存在的指针,这样你必须显示的调用IUnkonwn::AddRef来增加应用计数。否则,当你释放前面的那个接口指针的时候, 这个COM对象就会有可能被销毁,尽管你可能还需要这个拷贝的指针。
不管是你还你对象本身增加了引用计数,你都必须释放这个接口指针。当你不再需要这个接口指针的时候,你应该调用IUnknown::Release来减少引用计数的值。在实际的应用中,通常用NULL值来初始化指针变量,当你释放了这个指针的时候,你同样也需要把NULL值负给这个指针。这样允许你在你程序的清除代码段中测试所用的接口指针。这样如果指针的值不是NULL,说明这个些指针存在,在你的应用程序终止之前,你应该释放它们。
下面的代码段扩充了在“使用CON接口”一文中讨论的事例代码,以便举例说明如何处理引用计数:
IDirectSoundBuffer8 *pDSBPrimary = NULL ;
IDirectSound3DListener8 *pDSListener = NULL ;
IDirectSound3DListener8 *pDSListener2 = NULL ;
...
//Create the object and obtain an additional interface.
//The object increaments the reference count.
if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL )))
retrun hr ;
//Make a copy of the IDirectSound3DListener8 interface prointer
//Call AddRef to incremnet the reference count and to ensure that
//the object is not destroyed prematurely
pDSListener2 = pDSListener ;
pDSLintener2->AddRef() ;
...
//Cleanup code. Check to see if the pointers are still active.
//If they are, Call Release to release the interface.
if( pDSBPrimary != NULL )
{
pDSBPrimary->Release();
pDSBPrimary = NULL ;
}
if(pDSListener != NULL)
{
pDSListener->Release();
pDSListener = NULL;
}
if(pDSListener2 != NULL)
{
pDSListener2->Release();
pDSListener2 = NULL;
}
注: 由于翻译水平有限,错误在所难免。如发现翻译的不对的地方还请路上的朋友指正,谢谢
可以任意转载。
译者: closeall
MSN: closeall@hotmail.com
e_mail: closeall@126.com
2005.09.04 译