Memory leak despite calling Release

Started by
5 comments, last by tonemgub 10 years, 3 months ago

Hi guys

I have a bit of a problem. I created a render to texture system for blending certain textures together but despite my releasing those objects when I finish with them in the program (I don't release at shutdown, I release at the end of the cycle as the render only happens on command), the video memory in use does not decrease. Call the cycle additional times and it increases. Since the program on its own uses a sizeable amount of memory, users are running into OOM CTDs at times.

Anyone got an idea on how to fix this?

Thanks

JB

Advertisement

First of all, you need to double-check how you're measuring video memory in use. That may well be giving you misleading information.

Then you need to check your objects lifetimes. As D3D is COM-based, and as COM manages lifetimes by reference counts, this kind of problem is normally caused by something somewhere continuing to hold a reference to an object. Finding what that something is may not be so trivial, however.

D3D11 provides the ID3D11DeviceContext::ClearState call, which will unbind all state from your context, so using this before you destroy your objects can help; in D3D11 an object bound to the pipeline (e.g via PSSetShaderResources) will cause the context to hold a reference to that object (see the documentation for the various Set calls) so calling Release on it's own won't be enough to reduce the reference count to 0 and cause the object to be destroyed.

Alternatively, and if ClearState seems too drastic (the intention behind it's design seems to be to just use it before final shutdown to release any such outstanding references) you can always unbind that object, e.g by binding a different object in it's place, or by binding NULL.

Another possible cause is that you have other associated objects that you do not destroy. E.g you'll typically have a texture and one or more views (in your case a Shader Resource View and a Render Target View); if you Release the texture but not the view(s) (or the other way around) you'll leak.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Measuring the video memory using NVIDIA Inspector.

IUnknown::Release returns 0 for every instance of every object I have in use. Will try the ClearState though.

As for the shader resource views, there I release the view and the Texture2Ds that get created. The render targets are different though. There I keep the render target view until shutdown but I always increase the reference count when getting the resource to copy to system memory and then I release that resource afterwards to drop the reference count back down to what I had originally for the render target view.

Thanks a bunch.

Maybe not usefull, but I once looked for a similar cause for hours.

In the end I created two backbuffers by accident and only called release just once.

Good luck

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me


IUnknown::Release returns 0 for every instance of every object I have in use.

This is not an indication that the interface was released! Perhaps not even if you run Direct3D in debug mode - IIRC, debug mode has it's own reference counting mechanism, which is accessed via the debug layer, but it is not exposed in the return value of Release.

So if you are just calling Release() on each interface pointer until it returns 0, you are doing it wrong. You have to call Release as many times as you called AddRef, or any other function that caused the refcount to go up.

if you do call Release in a loop this way and it did actually return the remaining reference count, you would end up causing other interfaces that are shared from the same object to crash, since the reference count is usually a per-COM object value (it can be implemented per-interface, but the COM docs say you cannot make assumptions - you must always call Release EXACLTY as many times as you - or Direct3D - called AddRef).

After running things through the debugger I have verified that I have released the objects as many times as they were created. Still despite using the ClearState and Flush methods the video memory usage does not go down.

Any other ideas?

If Flush doesn't do anything, you probably still have some unreleased video resources that you create every cycle. Make sure you release all of the objects, not just the textures.

Also, this doesn't make sense to me, but I'm guessing this is where your problem is:


I always increase the reference count when getting the resource to copy to system memory and then I release that resource afterwards to drop the reference count back down to what I had originally for the render target view.

Normally, you do not need to call AddRef on any of those resources you're binding (or their views). The Set... methods do this themselves, and then they call Release when you call ClearState or the same Set methods with NULL. If you still have to call AddRef and Release yourself for some other reason, then you have to call Release a second time to actually get the resource to be fully deleted, because the first time you're only releasing the reference you allocated - but D3D still holds a reference from when the object was created.

This topic is closed to new replies.

Advertisement