[solved] WASAPIAudioIODevice crash in Windows 7 when closing audio device

when building a console application (or other apps which the main thread is not the juce message thread), the WASAPIAudioIODevice crashes when closing audio device.
It’s weird that this only happens in Windows 7 SP1 (I don’t know if this happens in earlier version like Windows 7 RTM or Windows Vista, because all our Windows 7 machine is in Windows 7 SP1), and never happen in Windows 10 (also no idea if this happens in Windows 8 or Windows 8.1).
A simple reproduction code would be like this:

#include "../JuceLibraryCode/JuceHeader.h"

class MessageThread : public Thread
{
public:
	MessageThread() : Thread("Message Thread")
	{
		messageThreadInitialised = false;
		startThread();
		while (!messageThreadInitialised) Thread::sleep(1);
	}

	~MessageThread()
	{
		MessageManager::getInstance()->stopDispatchLoop();
		stopThread(-1);
		messageThreadInitialised = false;
	}

	void run() override
	{
		ScopedJuceInitialiser_GUI gui;
		messageThreadInitialised = true;
		MessageManager::getInstance()->runDispatchLoop();
	}

private:
	bool messageThreadInitialised;
};

class MyAudioDevice
{
public:
	MyAudioDevice()
	{
		deviceManager.initialiseWithDefaultDevices(0, 2);
	}

private:
	AudioDeviceManager deviceManager;
};

int main (int argc, char* argv[])
{

	// ..your code goes here!
	MessageThread messageThread;
	MyAudioDevice *myAudioDevice;

	while (1)
	{
		myAudioDevice = new MyAudioDevice();
		delete myAudioDevice;
	}

    return 0;
}

And this will crash in Windows 7 SP1 with the following call stack:

WASAPICrashTest.exe!juce::ComSmartPtrjuce::WasapiClasses::WASAPIAudioIODeviceType::ChangeNotificationClient::release() 行 140 C++
WASAPICrashTest.exe!juce::ComSmartPtrjuce::IAudioSessionControl::operator=(juce::IAudioSessionControl * const newP=0x0000000000000000) 行 101 C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIDeviceBase::deleteSessionEventCallback() 行 550 C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIDeviceBase::closeClient() 行 458 C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIOutputDevice::close() 行 872 C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIAudioIODevice::close() 行 1167 C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIAudioIODevice::~WASAPIAudioIODevice() 行 989 C++
[外部代码]
WASAPICrashTest.exe!juce::AudioDeviceManager::~AudioDeviceManager() 行 96 C++
[外部代码]
WASAPICrashTest.exe!main(int argc=1, char * * argv=0x00000000002ae850) 行 91 C++
[外部代码]

this is the call stack using the latest JUCE modules on the master brunch, however It also crashes when using the JUCE modules on the develop brunch (but with a slightly different call stack).
Can you solve this?
Thanks!

I found a similar post 2 years ago, and it seems like the same issue:

So I think this is a really common issue of JUCE running in Windows 7.

update:
No need to start a message thread, and no need to close the audio device manually, so the simplest reproduction code is like this:

#include "../JuceLibraryCode/JuceHeader.h"

int main (int argc, char* argv[])
{
	CoInitializeEx(0, COINIT_APARTMENTTHREADED);

	AudioDeviceManager deviceManager;

	while (1) deviceManager.initialiseWithDefaultDevices(0, 2);

	return 0;
}

This will crash in windows 7 after a random amount of time (usually within 1 minute), and runs pretty stable in windows 10.
And using the JUCE modules on the master or the develop branch, the call stack at the time of the crash is the same.
Their call stacks are as follows:

WASAPICrashTest.exe!juce::ComSmartPtr<juce::WasapiClasses::WASAPIDeviceBase::SessionEventCallback>::release() line 140	C++
WASAPICrashTest.exe!juce::ComSmartPtr<juce::WasapiClasses::WASAPIDeviceBase::SessionEventCallback>::operator=(juce::WasapiClasses::WASAPIDeviceBase::SessionEventCallback * const newP=0x0000000000000000) line 101	C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIDeviceBase::deleteSessionEventCallback() line 550	C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIDeviceBase::closeClient() line 458	C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIOutputDevice::close() line 872	C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIAudioIODevice::close() line 1167	C++
WASAPICrashTest.exe!juce::WasapiClasses::WASAPIAudioIODevice::open(const juce::BigInteger & inputChannels={...}, const juce::BigInteger & outputChannels={...}, double sampleRate=44100.000000000000, int bufferSizeSamples=2205) line 1078	C++
WASAPICrashTest.exe!juce::AudioDeviceManager::setAudioDeviceSetup(const juce::AudioDeviceManager::AudioDeviceSetup & newSetup={...}, bool treatAsChosenDevice=false) line 538	C++
WASAPICrashTest.exe!juce::AudioDeviceManager::initialiseDefault(const juce::String & preferredDefaultDeviceName={...}, const juce::AudioDeviceManager::AudioDeviceSetup * preferredSetupOptions=0x0000000000000000) line 261	C++
WASAPICrashTest.exe!juce::AudioDeviceManager::initialise(int numInputChannelsNeeded=0, int numOutputChannelsNeeded=2, const juce::XmlElement * xml=0x0000000000000000, bool selectDefaultDeviceOnFailure=false, const juce::String & preferredDefaultDeviceName={...}, const juce::AudioDeviceManager::AudioDeviceSetup * preferredSetupOptions=0x0000000000000000) line 224	C++
WASAPICrashTest.exe!juce::AudioDeviceManager::initialiseWithDefaultDevices(int numInputChannelsNeeded=0, int numOutputChannelsNeeded=2) line 331	C++
WASAPICrashTest.exe!main(int argc=1, char * * argv=0x0000000000392380) line 102	C++
[external code]

Then in the crash location, the vs prompts are both: “this->p-> is nullptr.”

Hope these infomations will be helpful to you!

Thanks for the report, I’ve pushed a fix here:

Thanks ed! This works for us now.