1
Vote

Resource leak from _GetWIC()

description

_GetWIC() in DirectXTexP.h implements a singleton. The function stores a static pointer to a IWICImagingFactory. This resource is created on demand but never freed, showing up as a leak with some application verifiers.

Possible Workaround:
Caller can try _GetWIC()->Release() before exiting application.
The timing and code location of such cleanup may not be convenient.
EDIT: For whatever reason, calling Release() on the returned non-null pointer causes read access violation.

Proposed Solution:
As per other 3rd party libraries, create library Init() and Destroy() style functions. Perform whatever initialization and cleanup that may be required. Expose these functions with minimal dependency so they can be called at application startup and shutdown phases.

comments

walbourn wrote Jul 5, 2013 at 8:25 PM

Generally speaking, the WIC factory instance is expected to live the lifetime of the whole process... I'll see about adding some kind of 'cleanup', but generally singletons don't cleanup except by process teardown...

walbourn wrote Feb 21 at 7:33 PM

There's currently an issue with mixing the use of DirectXTex and DirectXTK today because they both define a _GetWIC() function. Either they need to be isolated to a specific module by themselves in each library, or one or both need to be renamed.

walbourn wrote Feb 21 at 7:34 PM

One possible solution to the original issue here would be to provide a 'SetWICFactory' method so the application can provide the instance instead of having the system create one internally. Then passing 'nullptr' could clean up the singleton. The DirectXTex and DirectXTK library functions don't retain a ref to the factory, so this would be fairly clean...

eloben wrote Sun at 12:50 PM

I am using only WICTextureLoader files inside a library. What I did is modify _GetWIC as follows:

static IWICImagingFactory* _GetWIC(bool cleanUp = false)
{
static IWICImagingFactory* s_Factory = nullptr;

if ( s_Factory )
{        
  if (cleanUp)
  {
    s_Factory->Release();
    s_Factory = nullptr;
    CoUninitialize();
  }
  return s_Factory;
}
...
}

Then just added a new public method CleanUp which calls _GetWIX(true):

void DirectX::CleanUpWIC()
{
_GetWIC(true);
}

This way you can ensure that after calling CleanUp the WIC factory is properly released.

walbourn wrote Sun at 7:12 PM

I agree that the actual cleanup is simple enough, but the challenge is that DirectXTex and DirectX Tool Kit do not have explicit 'initialization' and 'termination' interfaces at this point... If they get them, that would be a good solution.