Opening MidiInput without leak


#1

Howdy

I have the leak detector going off when I shut down my app.  Just trying to get basic midi input.

 

I have been checking some example code, commented out lots of code and isolated my leak to this line:

midiInput = MidiInput::openDevice(MidiInput::getDefaultDeviceIndex(), this);

In the destructor, there is midiInput->stop();

What is the proper way to open midi input, if I am doing it incorrectly?

 

Thank yall


#2

I was able to fix the leak by adding


    delete(midiInput);

to the destructor.


However, I keep reading that good practice is to not use 'delete' - could someone explain if I am doing this incorrectly?

 

Thank yall


#3

JUCE and C++11 provide classes to automatically handle dealing with object lifetimes when going out of scope.

Have a look at <a href="http://www.juce.com/api/classScopedPointer.html">juce::ScopedPointer</a>.


#4

Thanks a lot for the clarification - I read the blurb to use 'Scoped Pointers...etc'...but I wasn't sure which of those helpers I should be using. This helps a lot.

 

So is my 'delete' technique really not required / poor practice? Just curious if my solution is a hack or not.


#5

I'm creating my objects as scoped pointers now like so

ScopedPointer<MidiClass> myobject;

 

...first thing that threw me is my myobject.method() methods no longer work.

Changing them to myobject->method() throws an access violation after compile.


#6

So working this out - I think the above code is making a scoped pointer to something that doesn't exist - that would explain the access violation, yea? (I tried to copy how scoped pointers are called in the Juce Demo code).

So now I'm also trying ScopedPointer<MidiClass> midiobject (MidiClass *const midiobjecttemp);

but now when I call midiobject->returnvalue() - it says 'expression must have a pointer type'.

I'm trying to get a value from my midiobject via a method that simply returns the variable.


#7

Yeah, that's exactly the reason you're getting access violations. You need to initialise or assign an object to your ScopedPointer.

Example:

ScopedPointer<MidiInput> midiInputInstance (MidiInput::openDevice (MidiInput::getDefaultDeviceIndex(), this));

But, to be on the safe because you don't know if the result will be null or not, do something like this:

ScopedPointer<MidiInput> midiInputInstance (MidiInput::openDevice (MidiInput::getDefaultDeviceIndex(), this));

if (midiInputInstance != nullptr)    
    midiInputInstance->doStuff(); //doStuff() is supposed to be a method from the MidiInput class

So now I'm also trying ScopedPointer<MidiClass> midiobject (MidiClass *const midiobjecttemp);

Seems like you're mixing up writing functions/methods and declaring object instances, to me... 


#8

Thanks for the further push in the right direction.

It is very likely I'm mixing things up - I am just trying things to learn how this all plugs together. I have a basic understanding but there are certain things I'm confused about so I just try anyway.

 

Thanks so much...will report back.


#9

The code you provided to open the midiinput as a scoped pointer doesn't appear to work. Even if I take out the if statement, I'm no longer getting an active readout.

 

Also, my class that that function resides in is still leaking.

 

In the code that works (where I use 'delete'), I create a new object by saying

MidiClass midiobject;

 

I thought to convert this to scoped pointer would simply be:

ScopedPointer<MidiClass> midiobject;

 

But of course, that references nothing. So, how do I create this object as a scoped pointer, since it still appears to be the one leaking?

 

Thank you as always - much appreciated and I am enjoying figuring this stuff out. I am tempted to just keep the 'delete' since it works, but I'd love to do it 'right'.


#10

Since I don't have direct example code to see what you're doing wrong, the only thing I can say is to be sure you have an understanding between the stack and the heap.

If you declare an object as a ScopedPointer, you use it like you would normal heap objects, without the need to call delete on it when the object goes out of scope. In other words, you may create one using "new".

Silly-stupid example:

//Stack:
int myInt = 0;

Array<int> listOfInts;
listOfInts.add (100);

//Heap:
{
   ScopedPointer<AudioProcessor> myAudioProc (new AudioProcessorSubclass()); //Suggested way to init. a ScopedPointer - see ScopedPointer's class notes

   ScopedPointer<AudioProcessor> myOtherAudioProc;
   myOtherAudioProces = new OtherAudioProcessorSubclass());

   OwnedArray<AudioProcessor> listOfProcs;
   listOfProcs.add (new AudioProcessorSubclass());
} //When going out of scope, myAudioProc gets automatically deleted here, and so do any elements in the OwnedArray

#11

Howdy and thanks so much for your help.

 

Using your very nice example (with the 'new', etc), I was eventually able to nail this.

 

The solution was that I was declaring these thing in my header files in private sections - when I left the declaration in the header but moved the initialisation to the regular cpp file, things all worked fine.

 

If you can briefly tell me what that means, or point me in the right place to look it up, I would really appreciate it.

 

Thank you again for your help.


#12

I'm not sure how moving a ScopedPointer out of your class' scope fixed this because you have not given example code.

Technically, if you used a ScopedPointer in your class' scope, the object's lifetime should now (to some degree) be governed by the class: the destructor of the ScopedPointer is guaranteed to be called in your class' destructor.

Here's a Microsoft MSDN article explaining "scope" thoroughly, with small examples: http://msdn.microsoft.com/en-us/library/b7kfh662.aspx

Hopefully that helps clarify.


#13

Howdy again

I'm trying to clarify what fixed it as best I can, but I came in making a lot of trial and error changes so bear with me as I sort them out. Forgive my lingo if I mix up words, I am learning by doing so occasionally figure things incorrectly.

 

Originally, I was missing the connection between my midiInput object being declared in the header file and initialised in the cpp. I originally just copied your code straight up, but as I now think I know,that was redeclaring the MidiInput when it was already declared in the h file. When I simply changed the Line MidiInput* midiInput in the header to ScopedPointer<MidiInput> midiInput - it all started working.

 

The other confusing part (for me) was that I was trying harder to make the surrounding class around the midiInput a scoped pointer, which turned out to be unneccesarry.

 

Silly mistakes, yea, but I'm working through them. I started by just copying your code, but when I considered in relation to mine, I figured it out.

 

And apologies for not providing more code, I am trying to walk the fine line between 'point me in the right direction' and seeming like 'do it for me'.

 

Thank yall