"Detected memory leaks" when using class "MemoryBlock"


#1

Hello, everyone! I just started learning JUCE, in my project, I used “MemoryBlock” class by this way:

[code]class alignedMemoryBlock: public juce:: MemoryBlock
{
public:
OneBuffer (int L);
~ OneBuffer ();
void * alignP;
};

[/code]

and in the constructor:

[code]alignedMemoryBlock:: alignedMemoryBlock (int L): MemoryBlock (L +16, false)
{
int K = 0;
K = (int) getData ();
if (K == 0) {
BufferWrong ();
AignedP = 0;
return;
}
if (K% 16! = 0) {
K = K + (16-K% 16);
}
AignedP = (void *) (K);
}

[/code]

So I can get 16-byte aligned MemoryBlock.

Then I created a class:

[code]class FreqMath: FreqDel, FreqBase
{
private:
alignedMemoryBlock * REDE, * ER, * EI, * ERREV, * EIREV, * WEIGHTA, * XFADER, * BITREVNUMBERDEL, * BITREVNUMBERDEL2;



};

FreqMath:: FreqMath (int k, int D, int C): FreqBase (k), FreqDel (D)
{




REDE = new OneBuffer (LengthMax * 8,8);
EI = new OneBuffer (L * 8,8);
ER = new OneBuffer (L * 8,8);
EIREV = new OneBuffer (L * 8,8);
ERREV = new OneBuffer (L * 8,8);
XFADER = new OneBuffer (C * 8,8);
WEIGHTA = new OneBuffer ((LengthMax / 2 +1) * 8,8);
BITREVNUMBERDEL = new OneBuffer (Del * sizeof (int), 0);
BITREVNUMBERDEL2 = new OneBuffer (Del * 2 * sizeof (int), 0);
}

FreqMath:: ~ FreqMath ()
{
REDE-> ~ OneBuffer ();
ER-> ~ OneBuffer ();
EI-> ~ OneBuffer ();
ERREV-> ~ OneBuffer ();
EIREV-> ~ OneBuffer ();
WEIGHTA-> ~ OneBuffer ();
XFADER-> ~ OneBuffer ();
BITREVNUMBERDEL-> ~ OneBuffer ();
BITREVNUMBERDEL2-> ~ OneBuffer ();
}

[/code]

Finally, in the main function:

[code]# Include

Include “FreqMath.h”

int main () {
FreqMath A (4,2,8);
system (“pause”);
return 0;
}
[/code]

I think that’s good !
So I press F5, VC2011 told me:

Detected memory leaks!
Dumping objects ->
{281} normal block at 0x023B5CF8, 20 bytes long.
Data: <H]; > 48 5D 3B 02 CD CD CD CD 20 00 00 00 CD CD CD CD
{279} normal block at 0x023B5C58, 20 bytes long.
Data: < ; > A8 5C 3B 02 CD CD CD CD 10 00 00 00 CD CD CD CD
{277} normal block at 0x023B5B80, 20 bytes long.
Data: < [; H > D0 5B 3B 02 CD CD CD CD 48 00 00 00 CD CD CD CD
{275} normal block at 0x023B5AB0, 20 bytes long.
Data: < [; @ > 00 5B 3B 02 CD CD CD CD 40 00 00 00 CD CD CD CD
{273} normal block at 0x023B5A00, 20 bytes long.
Data: <PZ; > 50 5A 3B 02 CD CD CD CD 20 00 00 00 CD CD CD CD
{271} normal block at 0x023B5950, 20 bytes long.
Data: < Y; > A0 59 3B 02 CD CD CD CD 20 00 00 00 CD CD CD CD
{269} normal block at 0x023B4070, 20 bytes long.
Data: < X; > F0 58 3B 02 CD CD CD CD 20 00 00 00 CD CD CD CD
{267} normal block at 0x023B3FC0, 20 bytes long.
Data: < @; > 10 40 3B 02 CD CD CD CD 20 00 00 00 CD CD CD CD
{265} normal block at 0x023B3EB0, 20 bytes long.
Data: < ?; > 00 3F 3B 02 CD CD CD CD 80 00 00 00 CD CD CD CD
Object dump complete.

why? where I did wrong?THX!


#2

Wow. Does any of that really compile??

To explain all the mistakes in this code would take a very long time, I’m afraid. But your main question, “why is it leaking” is because of this:

FreqMath:: ~ FreqMath () { REDE-> ~ OneBuffer (); ER-> ~ OneBuffer (); EI-> ~ OneBuffer (); ERREV-> ~ OneBuffer (); EIREV-> ~ OneBuffer (); WEIGHTA-> ~ OneBuffer (); XFADER-> ~ OneBuffer (); BITREVNUMBERDEL-> ~ OneBuffer (); BITREVNUMBERDEL2-> ~ OneBuffer (); }

…which I can only describe as “WTF?” Where on earth did you pick up nonsense like that!?! Go and learn about how new/delete works in C++!

And then, when you do understand how new/delete works, stop using it! Always use object composition where possible, not pointers. And never inherit from a class like MemoryBlock, or anything that doesn’t have a virtual destructor. (The compiler must have warned you about that - don’t ignore it!). In general, you should never inherit at all if you can achieve the same result using object composition - there are lots of good c++ tutorials out there that give really good explanations of when you should use inheritance vs composition.


#3

While reading your code, I’ve been wondering several times in which language it was written :wink:

On a more serious note : under Visual C++, the memory leak checker isn’t usefull at all. Try the (free) VLD add on which displays the call stack of the allocation causing the leak.


#4

Looking at that code was a fun puzzle.

Anyway, Jules, the need for aligned data is real though. What about adding to MemoryBlock to support alignment?

I was wondering ‘what he/she should have done’ - apart from learning C++, obviously, and the best in the new scheme would presumably be a set of ScopedPointer for the buffers - we’ll assume they’re actually needed, but if you don’t advocate sub-classing MemoryBlock, then getting an aligned data pointer out of it would be clunky, right (without doing the math every time you need it, or risking keeping a raw pointer around)?

Bruce


#5

Just a helpful pointer, since we all piled on:

Something like:

class FreqMath: FreqDel, FreqBase { private: ScopedPointer <MemoryBlock> REDE, ER, EI, ERREV, EIREV, WEIGHTA, XFADER, BITREVNUMBERDEL, BITREVNUMBERDEL2; .................. ................. ............... };

Means that all your buffers will be automagically cleaned up for you when your FreqMath instance is deleted. Absent Jules’ tips earlier, I would personally have considered a MemoryBlock subclass, just overriding a constructor to add 16 bytes to each assignment, and adding a getAlignedData to pass back an aligned pointer to the data in the correct pointer type - not adding any members, since getting them deleted wouldn’t work.

But I read a lot of C++ books - still no expert, but I put the work in. It’s not a picnic, even with Juce. Check out the Wiki pages - I believe there’s tips about new pointer types.

Bruce


#6

Well…thank u all ! I think I understand where I did wrong…

Does this mean that when I do “~alignedMemoryBlock()” , in fact, it runs the MemoryBlock s destructor?
So somthing in “alignedMemoryBlock” has not been released form heap?

Is that right?

And…Im Sorry,I asked a Stupid question…
I started Learning C++ only a few months.


#7

You never call ~Anything.

As Jules said, the C++ new and delete keywords apply, you never explicitly call a destructor. You better look them up and get your head around it - if you just ‘solve’ your current problem, you will run into trouble later.

Bruce


#8

The best approach could be as simple as this:

[code]class AlignedMemoryBlock
{
public:
AignedMemoryBlock (int size) : block (size + 16) {}

void* getData() const    { return (void*) (((pointer_sized_int) block.getData() + 15) & ~15); }

private:
MemoryBlock block;
};[/code]

And you definitely shouldn’t use ‘new’ for objects like this, not even with a ScopedPointer - just embed the objects directly into their parent object and there’s no need to worry about creating or destroying them, e.g.

class FreqMath: FreqDel, FreqBase { private: AlignedMemoryBlock REDE, ER, EI, ERREV, EIREV, WEIGHTA, XFADER, BITREVNUMBERDEL, BITREVNUMBERDEL2; .................. ................. ............... };

And for god’s sake sort out that awful spacing and capitalisation!!


#9

Well…Thanks Everyone.
Today I have changed my code and it seems a lot better
And I copied the code … thank you jules
I will never use the "new / delete"like this, forever…

And…As Bruce said ,I think there are many people who need aligned data ,
for SSE things or something else.