Can someone help with a cleanup / leaks issue?


#1

 

Some silly thing is blocking my work, as a method that loads a short wave file triggers memory leaks detections.

I am working on a convolution plugin and this class can be used to play short audio files via the main process() method.

The class itself works fine in a remote host, but when I use a simple host for debugging, it triggers the leak detector (of course also in the remote host, but this isn't stopped by it).

I have tried to "delete reader;" but this crashes with a heap issue. Same with calling the destructor itself.

I also tried scoped pointers for all the members, but with the same results.

I guess I am running into a C++ thing that I am not yet aware of... I hope someone can help me with this silly thing.


void SamplePlayer::LoadSample(String fileName)
{
    WavAudioFormat waveFormat;
    File file(fileName);
    FileInputStream stream(file);
    AudioFormatReader* reader = waveFormat.createReaderFor(&stream, false);
    sampleBuffer->setSize(2, reader->lengthInSamples);
    reader->read(sampleBuffer, 0, reader->lengthInSamples, 0, true, true);

    // How to cleanup here?
    // delete reader; // crashes
    // ScopedPointers don't help
}

 


#2

You cannot have the stream on the stack.

The second parameter of createReaderFor do not refer to streaming owning but what to do in case the reader fail opening.

Leave delete reader and create the stream using new.


#3

This puzzles me, because I am receiving a valid and working reader within this method.

I can playback the sampleBuffer in another method.

The lifetime of the reader should be only within this method (above code). Why can't it be on the stack?

The documentation is clear on this: createReaderFor creates a new instance. So I think I can assign it to a pointer...

  "The reader object that is returned can be used to read from the stream, and should then be deleted by the caller."

The problem is IMHO only in how to delete it...


#4

Btw, I have no error checking in this method, because it will later be replaced with channel after channel buffers from a dedicated file containing a number of test sounds.

The above code works, I only get memory leak assertions as soon as the method ends.


#5

Why can't it be on the stack?

Because the reader will delete it, so you'll delete it twice unless you leak the reader!


#6

Thanks gentlemen!

Normally I try to spend hours to learn more - but in this case I was blocked from debugging other parts. So I asked you :-)

This is now working without problems:


void SamplePlayer::LoadSample(String fileName)
{
    WavAudioFormat waveFormat;
    File file(fileName);
    FileInputStream* stream = new FileInputStream(file);
    AudioFormatReader* reader = waveFormat.createReaderFor(stream, false);
    sampleBuffer->setSize(2, reader->lengthInSamples);
    reader->read(sampleBuffer, 0, reader->lengthInSamples, 0, true, true);
    delete reader;
}

#7

Ok, but *please* learn to use RAII - 'delete' is a dirty word in modern C++!


#8

ScopedPointer Jules... ? ;-)

Man, you must get so tired of all these C++ newbies... ;-)

I am glad that my plugin is going well in spite of struggling sometimes with C++.

I have a background in the Pascal languages (8 years developing and mainting some 80,000 lines in Modula-2 way back in the eighties) and later with Delphi. I still like them.

When I started with MS VC++ this summer I was struck how SLOW its compiling was. Delphi was a lot faster 10 years ago and also created very good optimized code. But C++ won, it's the standard for audio processing and I will keep on learning more about it.

Thanks for the great JUCE platform and hope to switch to a commercial license in a few months!

(although I still don't like the font rendering on Windows, hehe)

 

Here is an example of what I am working on. I sine-sweeped the Teldex Studio stage in Berlin and made a lot of great impulse responses from the recordings. This is a demo from these IRs and my plugin:

https://soundcloud.com/peter-emanuel-roos/samplicity-teldex-ir-reverb