[Solved ]Scoped Pointer Problem


#1

Hello,

I am using a scoped pointer in the following way:

if (buttonThatWasClicked == textButton)
{
    File file("C:\\Programming\\Mic1_C1.wav");
    FileInputStream stream(file);
    WavAudioFormat wavFormat;
    ScopedPointer<AudioFormatReader> reader; 
    reader = wavFormat.createReaderFor(&stream, false);
}

But when I run the function I get a MS-Windows error: "Debug Assertion Failed! – Expression: _CrtIsValidHeapPointer(pUserData)"
This happens when the programs has left the function and is trying to free memory. And the problem seems to be the AudioFormatReader in combination with the scoped pointer.

So I thought, maybe the scoped pointer is not right in this case. Therefore I changed it to a normal pointer, i.e.

...
WavAudioFormat wavFormat;
AudioFormatReader* reader;
reader = wavFormat.createReaderFor(&stream, false);
...

That works better. Now I can execute the function. BUT when I close down the program, I get a JUCE assertion, telling me, that I am leaking memory and that I should use scoped pointers.

So right now I am a bit confused :o and dont know, how to handle this correctly.


#2

Your ScopedPointer’s scope is wrong… Make it a class variable

Rail


#3

Unrelated-to-ScopedPointer hint: juce::AudioFormatManager::createReaderFor


#4

Thanks for the fast answers!

Actually it worked fine, to have the scoped pointer declared locally. ( Or do I need to change that? If yes, why? )

But I had to switch to AudioFormatManager and using the file directly. After that the problem was gone.
Here is my working code:

if (buttonThatWasClicked == textButton)
{
    File file("C:\\Programming\\Mic1_C1.wav");
    AudioFormatManager formatManager;            
    formatManager.registerBasicFormats();
    ScopedPointer<AudioFormatReader> reader;
    reader = formatManager.createReaderFor (file);
}

#5

What is it you are actually trying to do? The problem that was causing your crash that jrlanglois hinted at was that createReaderFor takes ownership of the stream that you pass in (i.e. it deletes it when it is no longer needed by the reader). Your stream was declared as a stack variable so was being deleted as soon as it went out of scope and now the stream the reader has a pointer to is invalid.

In your code you don’t actually seem to do anything with the reader so why are you creating one at all? Bear in mind that that your reader is deleted on the line after you assign it so you can’t access it anywhere else in your code.

One other small thing is that you should really initialise your ScopedPointer as you declare it:


#6

Actually I want to read a WAV file, and write it back as several smaller WAV-files (chopped). So I am going to add more code later on, which is going to use the reader.

And yes, I just tested: you are right about the stream. The reader will delete the stream, when it no longer needs it, but that does not work, because the stream is declared locally on the stack and therefore it got deleted already. So the following works as well:

    File file("C:\\Programming\\Mic1_C1.wav");
    FileInputStream* stream = new FileInputStream(file);
    WavAudioFormat wavFormat;
    ScopedPointer<AudioFormatReader> reader( wavFormat.createReaderFor(stream, false) ); 

I declared the stream on the heap instead. But that does not look very nice, I think. Maybe there would be a better solution?


#7

Personally I would probably write that all in one statement so you don’t have a pointer lying around that you might be tempted to hang onto or dereference later.

This obviously assumes that you know the file is a wav file. It’s probably better to use a single AudioFormatManager in your application somewhere and use that to create your readers, in a similar way to your second example.