Need help on runtime error of pure virtual function call(R6025) in VS2013


#1

Hi,

I met runtime error R6025 while programming tiny audio player. The error occurs when I close the application.

The program do simple job. Open the audio file, play or pause or stop it.  Following variables are in the class.


private:

//[UserVariables]   -- You can add your own custom variables in this section.
AudioDeviceManager _audioDeviceManager;

AudioFormatManager _audioFormatManager;

ScopedPointer<AudioFormatReaderSource> _audioFormatReaderSource;

AudioTransportSource _audioTransportSource;

AudioSourcePlayer _audioSourcePlayer;

The program has 4 button to open and play the audio file, and following is body of the function "ButtonClicked"


void MainEditor::buttonClicked (Button* buttonThatWasClicked)
{
    //[UserbuttonClicked_Pre]
    //[/UserbuttonClicked_Pre]
    if (buttonThatWasClicked == openButton)
    {
        //[UserButtonCode_openButton] -- add your button handler code here..
        FileChooser chooser("Select a Wave file to play...", File::nonexistent, "*.wav");
        if (chooser.browseForFileToOpen())
        {
            File file(chooser.getResult());
            _audioFormatReaderSource = new AudioFormatReaderSource(
                _audioFormatManager.createReaderFor(file), true);
            _audioTransportSource.setSource(_audioFormatReaderSource);
            playButton->setEnabled(true);
        }
        //[/UserButtonCode_openButton]
    }
    else if (buttonThatWasClicked == playButton)
    {
        //[UserButtonCode_playButton] -- add your button handler code here..
        if ((Stopped == _state) || (Paused == _state))
        {
            changeState(Starting);
        }
        else if (Playing == _state)
        {
            changeState(Pausing);
        }
        //[/UserButtonCode_playButton]
    }
    else if (buttonThatWasClicked == stopButton)
    {
        //[UserButtonCode_stopButton] -- add your button handler code here..
        if (Paused == _state)
        {
            changeState(Stopped);
        }
        else
        {
            changeState(Stopping);
        }
        //[/UserButtonCode_stopButton]
    }
    else if (buttonThatWasClicked == settingsButton)
    {
        //[UserButtonCode_settingsButton] -- add your button handler code here..
        bool showMIDIInputOptions = false;
        bool showMIDIOutputSelector = false;
        bool showChannelAsStereoPairs = true;
        bool hideAdvancedOptions = false;
        AudioDeviceSelectorComponent settings(_audioDeviceManager,
            0, 0, 1, 2,
            showMIDIInputOptions,
            showMIDIOutputSelector,
            showChannelAsStereoPairs,
            hideAdvancedOptions);
        settings.setSize(500, 400);
        DialogWindow::showModalDialog(juce::String("Audio Settings"),
            &settings,
            TopLevelWindow::getTopLevelWindow(0),
            Colours::white,
            true);
        //[/UserButtonCode_settingsButton]
    }
    //[UserbuttonClicked_Post]
    //[/UserbuttonClicked_Post]
}

And this is changeListenerCallback().


void MainEditor::changeListenerCallback(ChangeBroadcaster * src)
{
    if (&_audioDeviceManager == src)
    {
        AudioDeviceManager::AudioDeviceSetup setup;
        _audioDeviceManager.getAudioDeviceSetup(setup);
        if (setup.outputChannels.isZero())
        {
            _audioSourcePlayer.setSource(nullptr);
        }
        else
        {
            _audioSourcePlayer.setSource(&_audioTransportSource);
        }
    }
    else if (&_audioTransportSource == src)
    {
        if (_audioTransportSource.isPlaying())
        {
            changeState(Playing);
        }
        else
        {
            if ((Stopping == _state) || (Playing == _state))
            {
                changeState(Stopped);
            }
            else if (Pausing == _state)
            {
                changeState(Paused);
            }
        }
    }
}

Plus, this is some part of the constructor.


//[Constructor] You can add your own custom stuff here..
playButton->setEnabled(false);
stopButton->setEnabled(false);
_audioFormatManager.registerBasicFormats();
_audioSourcePlayer.setSource(&_audioTransportSource);
_audioDeviceManager.addAudioCallback(&_audioSourcePlayer);
_audioDeviceManager.initialise(0, 2, nullptr, true);
_audioDeviceManager.addChangeListener(this);
_audioTransportSource.addChangeListener(this);
//[/Constructor]

The code I referenced was from the book "Getting statred with JUCE", Chapter 4 : "Adding audio file playback support".

 

There's sample code of the book so compiled it and met same error.

I need some help not only to fix this but also tell this issue to the book publisher to fix it.

Can you get what's the problem?


#2


>    BMSPlayer.exe!_NMSG_WRITE(int rterrnum) line 226
     BMSPlayer.exe!_purecall() line 55
     BMSPlayer.exe!juce::AudioDeviceManager::audioDeviceStoppedInt() line 801
     BMSPlayer.exe!juce::AudioDeviceManager::CallbackHandler::audioDeviceStopped() line 67
     BMSPlayer.exe!juce::WasapiClasses::WASAPIAudioIODevice::stop() line 1034
     BMSPlayer.exe!juce::WasapiClasses::WASAPIAudioIODevice::close() line 985
     BMSPlayer.exe!juce::WasapiClasses::WASAPIAudioIODevice::~WASAPIAudioIODevice() line 834
     [External Code]    
     BMSPlayer.exe!juce::ContainerDeletePolicy<juce::AudioIODevice>::destroy(juce::AudioIODevice * object) line 48
     BMSPlayer.exe!juce::ScopedPointer<juce::AudioIODevice>::operator=(juce::AudioIODevice * const newObjectToTakePossessionOf) line 141
     BMSPlayer.exe!juce::AudioDeviceManager::~AudioDeviceManager() line 107
     BMSPlayer.exe!MainEditor::~MainEditor() line 92
     [External Code]    
     BMSPlayer.exe!juce::Component::SafePointer<juce::Component>::deleteAndZero() line 2154
     BMSPlayer.exe!juce::ResizableWindow::clearContentComponent() line 100
     BMSPlayer.exe!juce::ResizableWindow::~ResizableWindow() line 70
     BMSPlayer.exe!juce::DocumentWindow::~DocumentWindow() line 79
     [External Code]    
     BMSPlayer.exe!juce::ContainerDeletePolicy<BMSPlayerApplication::MainWindow>::destroy(BMSPlayerApplication::MainWindow * object) line 48
     BMSPlayer.exe!juce::ScopedPointer<BMSPlayerApplication::MainWindow>::operator=(BMSPlayerApplication::MainWindow * const newObjectToTakePossessionOf) line 141
     BMSPlayer.exe!BMSPlayerApplication::shutdown() line 39
     BMSPlayer.exe!juce::JUCEApplicationBase::shutdownApp() line 292
     BMSPlayer.exe!juce::JUCEApplicationBase::main() line 244
     BMSPlayer.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) line 100
     [External Code]    
     [아래 프레임은 올바르지 않거나 누락되었거나 kernel32.dll에 대해 로드된 기호가 없음]   

I think the problem is related with AudioDeviceManager but can't get what the very matter is... 


#3

It is probably because the _audioSourcePlayer is not removed from _audioDeviceManager callback prior to shutdown.

You should do a _audioDeviceManager.removeAudioCallback(&_audioSourcePlayer) in your shutdown code.


#4

Wow...! Thanks!! It works ^0^

How did you find the cause so fast? 'o'


#5

I'm pretty good at that :) Anyway, this line was the giveaway:

> BMSPlayer.exe!juce::AudioDeviceManager::audioDeviceStoppedInt() line 801

where the AudioDeviceManager will call attached callbacks.


#6

I see... ^~^ Thank you for your service!