I have been fooling around with the mediafoundation SDK lately, and have encountered something pretty odd.
Using the following piece of code, some DLLs get loaded into my process during runtime. (e.g. mf.dll), and are never released. (Even after calling CoUninitialize)
Does anyone know what could possibly cause this? Should I be worried about memory leaks?
I have also noticed that calling CoInitialize and CoUninitialize directly after, does not release DLLs loaded by CoInitialize. Is there any reason for this?
int main()
{
HRESULT hr = CoInitialize(NULL);
{
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
IMFSourceReader* pReader = nullptr;
hr = MFCreateSourceReaderFromURL(L"C:\\sometestvideo.mp4", nullptr, &pReader);
pReader->Release();
pReader = nullptr;
hr = MFShutdown();
}
}
CoUninitialize();
while(true)
{
Sleep(1000);
CoFreeUnusedLibraries();
}
return 0;
}
You don't need to worry, it's not the test which indicates a leak. More to this, the Media Foundation libraries report OK for unload, it's COM which does not need to unload right away. This is how you can check this out:
while(true)
{
static LPCTSTR g_ppszNames[] =
{
_T("mf.dll"),
_T("mfreadwrite.dll"),
};
for(SIZE_T nIndex = 0; nIndex < _countof(g_ppszNames); nIndex++)
{
HMODULE hModule = GetModuleHandle(g_ppszNames[nIndex]);
if(!hModule)
continue;
HRESULT (STDMETHODCALLTYPE *pDllCanUnloadNow)() = (HRESULT (STDMETHODCALLTYPE *)()) GetProcAddress(hModule, "DllCanUnloadNow");
_tprintf(_T("%s DllCanUnloadNow 0x%08X\n"), g_ppszNames[nIndex], (pDllCanUnloadNow)());
}
Sleep(1000);
CoFreeUnusedLibraries();
}
See also: PRB: DLLs Not Unloaded After Calling CoFreeUnusedLibraries
CoFreeUnusedLibraries does not immediately release DLLs that have no active object. There is a ten minute delay for multithreaded apartments (MTAs) and neutral apartments (NAs). For single-threaded apartments (STAs), there is no delay. The ten minute delay for CoFreeUnusedLibraries is to avoid multithread race conditions caused by unloading a component DLL.
To work around the problem, make a second call to CoFreeUnusedLibraries after ten minutes, or make periodic calls to CoFreeUnusedLibraries. For applications that run for long periods, such as Windows NT Service applications, calling CoFreeUnusedLibraries periodically ensures that DLLs that are not being used are unloaded.
Another workaround is to call CoUninitialize, which closes the COM library and releases all resources used by the current thread.