C#客户端中ATL COM对象的引用计数即使使用接口指针的FinalEleaseComObject也不会下降到零
我开发了一个简单的atl COM对象并创建了connectionpoint。接口类型的comobject是sink函数中的参数。我已经在连接点中的火灾事件和atlcom.h InternalAddRef/InternalRelease中设置了断点。就在fire事件之前,引用的数量是1,但当它到达C#中的sink函数时,它增加到2,一旦进入C#delegate,它就变成3。当我为接口调用FinalEleaseComObject时,它从3减少到1,但没有减少到0,因此不会调用对象析构函数并创建泄漏。请帮助我了解如何将ref计数设置为0并避免泄漏C#客户端中ATL COM对象的引用计数即使使用接口指针的FinalEleaseComObject也不会下降到零,c#,visual-studio-2010,atl,C#,Visual Studio 2010,Atl,我开发了一个简单的atl COM对象并创建了connectionpoint。接口类型的comobject是sink函数中的参数。我已经在连接点中的火灾事件和atlcom.h InternalAddRef/InternalRelease中设置了断点。就在fire事件之前,引用的数量是1,但当它到达C#中的sink函数时,它增加到2,一旦进入C#delegate,它就变成3。当我为接口调用FinalEleaseComObject时,它从3减少到1,但没有减少到0,因此不会调用对象析构函数并创建泄漏。
ret = p_IHUSNVRLyrEvents->OnLivePacket(Packet);//RefCount=1;From the connection point
Ref Count = 1
> atl100.dll!AtlInternalQueryInterface() + 0x9f bytes
> HUSNVRLayer.dll!ATL::CComObjectRootEx<ATL::CComMultiThreadModel>::InternalAddRef() Line 2622 C++
HUSNVRLayer.dll!ATL::CComObject<CPacket>::AddRef() Line 2870 C++
atl100.dll!AtlInternalQueryInterface() + 0x42 bytes
HUSNVRLayer.dll!ATL::CComObjectRootBase::InternalQueryInterface(void * pThis, const ATL::_ATL_INTMAP_ENTRY * pEntries, const _GUID & iid, void * * ppvObject) Line 2453 + 0x18 bytes C++
HUSNVRLayer.dll!CPacket::_InternalQueryInterface(const _GUID & iid, void * * ppvObject) Line 111 + 0x3a bytes C++
HUSNVRLayer.dll!ATL::CComObject<CPacket>::QueryInterface(const _GUID & iid, void * * ppvObject) Line 2884 C++
Ref Count = 2
> HUSNVRLayer.dll!ATL::CComObjectRootEx<ATL::CComMultiThreadModel>::InternalAddRef() Line 2622 C++
HUSNVRLayer.dll!ATL::CComObject<CPacket>::AddRef() Line 2870 C++
Ref Count = 3
> HUSNVRLayer.dll!ATL::CComMultiThreadModel::Decrement(long * p) Line 359 C++
HUSNVRLayer.dll!ATL::CComObjectRootEx<ATL::CComMultiThreadModel>::InternalRelease() Line 2629 + 0x9 bytes C++
HUSNVRLayer.dll!ATL::CComObject<CPacket>::Release() Line 2873 + 0xb bytes C++
Ref Count = 2
When i reach the .Net Code and enter inside the refcount is 3
ret=p_ihunsvrylevents->OnLivePacket(Packet)//RefCount=1;从连接点
参考计数=1
>atl100.dll!AtlInternalQueryInterface()+0x9f字节
>HUSNVRLayer.dll!ATL::CCOMObjeToRoTeX::NealAldReFuffor(2622 C++)
HUSNVRLayer.dll!AtL::CCOMObj::AddReFor(2870 C++)
atl100.dll!AtlInternalQueryInterface()+0x42字节
HUSNVRLayer.dll!ATL::CCOMObjeCurtOutBase::IntualQueQue界面(Valu**PITS,const ATL::AtAtLyInPMAPITIONTRON*PANSITS,CONST.GUIDI&IID,Value*PPVObjt)行2453 +0x18字节C++
HUSNVRLayer.dll!CyBase::InIngalQueQue界面(const gui&iID,Value*ppvObjts)行111 +0x3a字节C++
HUSNVRLayer.dll!ATC::CCOMObjult::QueryInterface(const uGuID&IID,Value*ppvObjor)2884行C++
参考计数=2
>HUSNVRLayer.dll!ATL::CCOMObjeToRoTeX::NealAldReFuffor(2622 C++)
HUSNVRLayer.dll!AtL::CCOMObj::AddReFor(2870 C++)
参考计数=3
>HUSNVRLayer.dll!ATC::CCOMultTHEADEDMALL::减量(长*p)359 C++
HUSNVRLayer.dll!ATL::CCOMObjeTrtoToEX::内部释放()行2629 +0x9字节C++
HUSNVRLayer.dll!AcL::CCOMObjult::RelaseEo()行2873 +0xB字节C++
参考计数=2
当我到达.Net代码并在内部输入时,refcount是3
如果您看到FinalReleaseComObject的文档:通过将其引用计数设置为0,释放对运行时可调用包装(RCW)的所有引用。这并不保证基础com对象的释放。您能在InternalAddRef中看到堆栈跟踪吗?这可能会告诉您谁在引用您的com对象。根据文档,通过调用FinalEleaseComObject,引用计数应为零,但在调试atlcom.h时,引用计数仍为1,但FinalEleaseComObject返回zero@oguz我通过在FinalEleaseComObject上保持断点,并在命中该断点时在上放置断点来确认这一点内部释放。在进入内部版本时,我可以看到ref count为3,它一直递减到1,然后退出(理想情况下ref count应该一直减少到0..调用对象的析构函数是由COM控制的,但ref count应该为零,对吗?我的水晶球说IConnectionPoint;;Unadvise()未调用。换句话说,您忘记取消订阅事件处理程序。引用计数问题不应“修复”对于Marshal.FinalReleaseComObject,这只是隐藏了一个bug。这就是为什么我要检查InternalAddRef中的堆栈跟踪,而不是InternalRelease中的堆栈跟踪。或者两者都检查,并比较添加/释放堆栈跟踪。这可能会告诉您哪个添加堆栈跟踪没有释放COM对象