I am just learning directx. One typically creates a directx device and several other COM interfaces through a functions calls such as
ID3D11CreateDeviceAndSwapChain(.... ,& device, ...);
In all tutorial code I have seen, the com interfaces are released using something akin to
if (pointer_to_com_object) {
pointer_to_com_object->Release();
pointer_to_com_object = 0;
}
e.g. the following is taken from Tutorial07_2008 in the directx 11 tutorials from Microsoft.
if( g_pSamplerLinear ) g_pSamplerLinear->Release();
if( g_pTextureRV ) g_pTextureRV->Release();
if( g_pCBNeverChanges ) g_pCBNeverChanges->Release();
if( g_pCBChangeOnResize ) g_pCBChangeOnResize->Release();
if( g_pCBChangesEveryFrame ) g_pCBChangesEveryFrame->Release();
if( g_pVertexBuffer ) g_pVertexBuffer->Release();
if( g_pIndexBuffer ) g_pIndexBuffer->Release();
if( g_pVertexLayout ) g_pVertexLayout->Release();
if( g_pVertexShader ) g_pVertexShader->Release();
if( g_pPixelShader ) g_pPixelShader->Release();
if( g_pDepthStencil ) g_pDepthStencil->Release();
if( g_pDepthStencilView ) g_pDepthStencilView->Release();
if( g_pRenderTargetView ) g_pRenderTargetView->Release();
if( g_pSwapChain ) g_pSwapChain->Release();
if( g_pImmediateContext ) g_pImmediateContext->Release();
if( g_pd3dDevice ) g_pd3dDevice->Release();
As pointed out in answers to this question COM objects can have references to them you don't own.
So is the above a bad way to clean up directx or do directx COM objects never have references to them you didn't create?
I just ask because I keep seeing it done this way as I am learning.
COM objects are reference counted. When you call Release(), you are effectively decrementing the internal reference count. If another object still owns a reference, it will not get destroyed.
If some other part of the application end up having a new reference to a COM object, make sure you call Release() when you are done with it. Carefully read documentation of methods that return references to know if you have to call Release() or not. Usually you will have to.
For instance in IDirect3DTexture9::GetSurfaceLevel documentation:
Calling this method will increase the
internal reference count on the
IDirect3DSurface9 interface. Failure
to call IUnknown::Release when
finished using this IDirect3DSurface9
interface results in a memory leak.
Related
We have some legacy software code, which uses COM. I've noticed that at one place, we perform a queryInterface on an IInspectable pointer, but dont bother calling release.
For ex:
void foo(IInspectable* myInterface)
{
ComPtr<OBJTYPE> pObj;
auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
if (hr != S_OK)
{
return hr;
}
//some code that uses pObj
}
I added Release to the above code like below :
auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
if (hr != S_OK)
{
return hr;
}
myInterface->Release(); //<-- Is this the correct way to release ?
//some code that uses pObj;
But I see that the above code crashes at times in the above function during release. Is there something wrong in the way I'm releasing the interface ? I can confirm that myInterface is not being used anywhere else in the function after the Release statement.
Apologies for not being able to copy/paste the actual code, but the above code summarizes pretty much the suspect code that I'm debugging. Basically what I want to know is, in the above scenario, do I need to call Release() ? And is this is the right place/way to call Release() ? Do I need to add any other safety checks in place ?
In the first foo function you should NOT call myInterface->Release(). Every call to Release should be paired with an adding of a reference. In that function you don't do myInterface->AddRef, so if you add myInterface->Release then your function will decrement the reference count by one, which does not seem like correct behaviour.
Conceptually, you should call AddRef on entry to the function and Release on exit of the function. Even though the reference count is "intrusive" in COM, the recommended coding style is to treat each interface pointer like it has its own reference count.
This is normally wrapped up in smart pointer classes. But when working with a function that receives a raw "in" interface pointer, this Add and Release can be "optimized" by just omitting both of those calls in the function, and treating the pointer like an observer pointer.
The call to QueryInterface will implicitly do pObj->AddRef() but this is nothing to do with myInterface. When you are finished with pObj a pObj->Release() should occur -- but this is managed by the ComPtr wrapper, you shouldn't add an explicit call.
I have a C++/CLI method, ManagedMethod, with one output argument that will be modified by a native method as such:
// file: test.cpp
#pragma unmanaged
void NativeMethod(int& n)
{
n = 123;
}
#pragma managed
void ManagedMethod([System::Runtime::InteropServices::Out] int% n)
{
pin_ptr<int> pinned = &n;
NativeMethod(*pinned);
}
void main()
{
int n = 0;
ManagedMethod(n);
// n is now modified
}
Once ManagedMethod returns, the value of n has been modified as I would expect. So far, the only way I've been able to get this to compile is to use a pin_ptr inside ManagedMethod, so is pinning in fact the correct/only way to do this? Or is there a more elegant way of passing n to NativeMethod?
Yes, this is the correct way to do it. Very highly optimized inside the CLR, the variable gets the [pinned] attribute so the CLR knows that it stores an interior pointer to an object that should not be moved. Distinct from GCHandle::Alloc(), pin_ptr<> can do it without creating another handle. It is reported in the table that the jitter generates when it compiles the method, the GC uses that table to know where to look for object roots.
Which only ever matters when a garbage collection occurs at the exact same time that NativeMethod() is running. Doesn't happen very often in practice, you'd have to use threads in the program. YMMV.
There is another way to do it, doesn't require pinning but requires a wee bit more machine code:
void ManagedMethod(int% n)
{
int copy = n;
NativeMethod(copy);
n = copy;
}
Which works because local variables have stack storage and thus won't be moved by the garbage collector. Does not win any elegance points for style but what I normally use myself, estimating the side-effects of pinning is not that easy. But, really, don't fear pin_ptr<>.
int atClass1::read_file
(String^ file_path, /* Path tofile */
HdfCallVars % ret_vals)
This is my function. Within it I have lots of native c++ code. I ran into a serious problem though
/* Iterate through the links, filling in needed data as discovered. */
io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,
&i, get_sonar_data, (void*)& ret_vals);
will not compile! Says ret_vals is managed and I can't do pointerey ampersandey stuff to it. Am I in trouble? Or is there a way out of my dilemma? The H5 function is a call into the HDF5 library.
thanks,
saroj
In .Net there is no guarantee that an object will remain on it current memory position as the garbage collector will "compact" the heap space when it wants to.
To get a native pointer to a managed object you should "pin" the object:
pin_ptr<HdfCallVars> pinned = &ret_vals;
io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,
&i, get_sonar_data, (void*)pinned);
Note that the pointer will be unpinned after the variable pinned goes out of scope, if H5Literate stores the pointer for future use, you should pin the value using System::Runtime::InteropServices::GCHandle, like this:
GCHandle ^handle = GCHandle::Alloc(ret_vals);
io_err = H5Literate (group_id, H5_INDEX_NAME, H5_ITER_NATIVE,
&i, get_sonar_data, (void*)handle->AddrOfPinnedObject());
When you don't need the pointer anymore, you should free it:
handle->Free();
May I ask something about hooking method in COM Distach Interface?
Recently, I am making some utility which is kind of COM monitoring tool.
and I'm trying to hook Com object's interface while running time.
for that, I needed to use type lib.
following is a outline of my codes.
// Load Type Lib.
LoadRegTypeLib( TypeLibCLSID , wMajorVersion , wMinorVersion , lcid , &pTypeLib );
// Get Function Descriptor
pInterfaceTypeInfo->GetFuncDesc( iii , &pfuncdesc );
// Create Instance and Get Interface
CoCreateInstance( pClassAttr->guid , NULL, ClassContext, pInterfaceAttr->guid , (void**)&pUnknownObject );
// Get VTable
dwOrgFunctionPointer = *(DWORD*)pUnknownObject;
// adjust offset
dwOrgFunctionPointer += pfuncdesc->oVft;
// Get Function Pointer
dwOrgFunctionPointer = *(DWORD*)dwOrgFunctionPointer ;
// Hook
MyHookMethod( dwOrgFunctionPointer );
This was successful until I found some Com Object which has Dispatch Interface (not dual).
If some Com Object has just Dispatch Interface ( not dual ), there is no function pointers in VTable.
There are just MFC's function pointers like a GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke.
moreover, pfuncdesc->oVft is always 0 for all functions belongs to that interface.
I know that I shoud use 'Invoke' method when I use these kind of com objects.
But problem is that Im trying to hook. I need function pointers.
How can I get those function pointers from IDispatch ?
There are only MFC's function pointers in IDispatch->vtable.
any advice will be appreciated.
Thnak you.
To Hook IDispatch, you can hook/shim all the methods of IDispatch, probably focussing mostly on Invoke. A key thing to remember is that IDispatch is that it is a very special interface. While COM rules ensure that QI for IID_IDispatch returns a single implementation, other interfaces derived from IDispatch can choose to have their own separate implementations of Invoke et al. Which means that casting to IDispatch can yield different results from QI-ing for it. I find this behaviour confusing but some classic AX scenarios require it.
Having said that, I strongly recommend against hooking in this way except perhaps for debugging purposes. Do not ship code that works this way in real app code. It will turn out to be very unstable.
Martyn
Am working on a .Net windows application which internally uses a COM dll.
Out of the following 4 ways of releasing a COM object, which is the best one?
1.
if (obj != null)
{
Marshal.ReleaseComObject(obj);
}
2.
if (obj != null)
{
Marshal.ReleaseComObject(obj);
obj=null;
}
3.if (obj != null)
{
Marshal.FinalReleaseComObject(obj);
}
4.if (obj != null)
{
Marshal.FinalReleaseComObject(obj);
obj=null;
}
Thanks for reading.
Either just let the GC deal with it as Richard suggested, or your number 2. If you call FinalReleaseComObject, you will destroy the runtime callable wrapper, regardless if it's found its way to other parts of your code as well. This could seriously confuse other parts of your code. So you should only call ReleaseComObject once per crossing-into-.NET-land-from-COM transition.
5. Let the GC do it.
Which is fine unless the COM component is holding on to significant resources you need.
If you are basing your approach on checking obj != null then setting obj to null is a good idea, unless you are sure this code will not be called multiple times.
The best way: need more details about the implementation of your application to give specific advise between use of ReleaseComObject and FinalReleaseComObject, but ideally the answer would be neither.