Games for Windows and the DirectX SDK blog

Technical tips, tricks, and news about game development for Microsoft platforms including desktop, Xbox, and UWP


Project maintained by walbourn Hosted on GitHub Pages — Theme by mattgraham
Home | Posts by Tag | Posts by Month

Known Issues - XAudio 2.7

audio, dxsdk

Originally posted to Chuck Walbourn's Blog on MSDN,

The XAudio2 library in the legacy DirectX SDK makes use of COM creation and reference counting for lifetime management, and a recent investigation has found a problem in this implementation. In short: in some situations the XAudio DLL itself is unloaded before the XAudio2 objects are completely destroyed, thus leading to an access violation. This normally happens on exit, although the exact details of when it might be evident depends on exactly which version of Windows you are using and the overall process layout for your application.

Update: This issue does not affect XAudio 2.8 (Windows 8 SDK), XAudio 2.9 (Windows 10 SDK), XAudio2 on Xbox 360, or XAudio2 on Xbox One. There is now a NuGet package for using XAudio 2.9 down-level on Windows 7 Service Pack 1, Windows 8.0, and Windows 8.1. See Microsoft Docs for details. Using this new version avoids this known issue.

An application level workaround is very easy to implement, and is already implemented in DirectX Tool Kit for Audio and in the XAudio2 DirectX SDK refreshed samples on GitHub.

Before your first XAudio object creation, you should create an explicit reference to the DLL and hold on to it.

#if ( _WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
HMODULE g_XAudioDLL = nullptr;
#endif
#if ( _WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
#ifdef _DEBUG
g_XAudioDLL = LoadLibraryExW( L"XAudioD2_7.DLL", nullptr, 0x00000800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ );
#else
g_XAudioDLL = LoadLibraryExW( L"XAudio2_7.DLL", nullptr, 0x00000800 /* LOAD_LIBRARY_SEARCH_SYSTEM32 */ );
#endif
if ( !mXAudioDLL )
    // error
#endif
DWORD creationFlags = 0;
#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG)
creationFlags |= XAUDIO2_DEBUG_ENGINE;
#endif
IXAudio2* pXAudio2 = nullptr;
HRESULT hr = XAudio2Create( &pXAudio2, creationFlags, XAUDIO2_DEFAULT_PROCESSOR );
if ( FAILED(hr) )

From here on, you work with XAudio2 as normal, delete objects, etc. Later after you do all cleanup and are fully done with working with XAudio2, you release the “extra” DLL reference:

if (pXAudio2)
    pXAudio2->Release();

#if ( _WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
if (g_XAudioDLL)
{
    FreeLibrary(g_XAudioDLL);
    g_XAudioDLL = nullptr;
}
#endif

This ensures that the DLL is not unloaded while XAudio2 objects are active.

Note: The use of LoadLibraryEx above with the LOAD_LIBRARY_SEARCH_SYSTEM32 flag is a security best practice.  For a Windows 7 system, this requires the KB 2533623 update to be installed.

See also: XAudio2 and Windows 8, Learning XAudio2, Windows 10 SDK RTM