deleteAndZero() prop


#1

Hello,

why not putting a test inside the macro deleteAndZero() as :

if(pointer) delete(pointer); (pointer)=0;

then, why is deleteAndZero not systematically used in juce classes ?

For instance, if you make your own DocumentWindow inheriting from juce::DocumentWindow, you have to be a little careful in the destructor,
a simple “deleteAllChildren()” rises a bug when juce::DocumentWindow tries then to destructe the titleButtons… :


a simple suggestion, this is I think a lightly work to do, and would not have strong consequences in terms of performance.


#2

On another almost non-issue with deleteAndZero, if you precede it with an if() yourself you need to be careful.

if(object) deleteAndZero(object); else Logger::outputDebugString(T("blah blah"));
is turned into this by the preprocessor:

if(object) { delete (object); (object) = 0; }; else Logger::outputDebugString((L"blah blah"));
which means the ‘else’ is dangling after a semicolon and doesn’t compile.

Of course you can do:

if(object) { deleteAndZero(object); } else Logger::outputDebugString(T("blah blah"));
or even:

if(object) deleteAndZero(object) else Logger::outputDebugString(T("blah blah"));
…just though it might catch someone else out (took me a while starring at the code to figure out wat was going on).

Not really sure it needs fixing, although the test for non-zero would be useful (and I think is what the docs say it does).
http://www.rawmaterialsoftware.com/juce/api/juce__Memory_8h.html#7d732d5964ce0d1a313face84230b1a0

(BTW on this page the docs for “#define juce_ThreadLocal __thread” seems to be describing “#define juce_UseDebuggingNewOperator”, looks like there needs some DOXYGEN condition in there somewhere.)


#3

[quote=“martinrobinson”]On another almost non-issue with deleteAndZero, if you precede it with an if() yourself you need to be careful.

if(object) deleteAndZero(object); else Logger::outputDebugString(T("blah blah"));
is turned into this by the preprocessor:

if(object) { delete (object); (object) = 0; }; else Logger::outputDebugString((L"blah blah"));
which means the ‘else’ is dangling after a semicolon and doesn’t compile.
[/quote]

that’s the reason why multi-statement macros should be wrapped in a do{}while(0) without semi colon

http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Multi-statement_Macro


#4

there is no need to test if the pointer is non zero in the deleteAndZero macro, since deleting a zero pointer is perfectly ok.

On the window delete problem, it would not be so easy to fix:

your class destructor will be called before the base DocumentWindow destructor, so you are calling deleteAllChildren, which deletes all the children without know anything about the local pointers of the buttons in the base DocumentWindow which will remain dangling ones: even if you put deleteAndZero here you will have problmes the same.

there’s nothing you can do here, unless you clean the dngling pointers yourself.


#5

:oops: I’ve always been over-cautious then with NULL pointers even when freeing. Thanks for that.


#6

[quote]that’s the reason why multi-statement macros should be wrapped in a
Code:
do{}while(0)
without semi colon [/quote]

…yes, I’ve been meaning to use that in a few places. Might do a few tweaks now, while you’ve reminded me.

I did exactly the same thing for years!


#7

Ah - I just remembered why I never used the do {} while (false) thing: it’s because you get bombarded by compiler warnings about the conditional expression being constant…


#8

How is

do { something } while (0)

different from:

{ something }

?


#9

[quote=“matt”]How is

do { something } while (0)

different from:

{ something }

?[/quote]

when it’s a #define

(I think we just designed the new front and back of a ThinkGeek T-Shirt, perhaps too late for Christmas…)

deleteAndZero is #define’d:

so doing:

expands to:

There is now an unnecessary, but normally harmless semicolon. But in my earlier post with if/else the extra semicolon is not harmless. You could miss out the extra semicolon but that misses the point with a macro like deleteAndZero where it should FEEL like a function call. The do/while thing means there are no extra semicolons.


#10

Yiha, interesting debate…

Normally it behaves like that, but I got few days ago an execution crash cause my deleteAllChildren in destructor was destructing DocumentWindow children too !! :shock:…and I was pointed to “titleButton”… Anyway, maybe I made a mistake somewhere… but.


#11

[quote=“asair”]Yiha, interesting debate…
Normally it behaves like that, but I got few days ago an execution crash cause my deleteAllChildren in destructor was destructing DocumentWindow children too !! :shock:…and I was pointed to “titleButton”… Anyway, maybe I made a mistake somewhere… but.[/quote]

i usually tend to avoid messing too much with components inside my windows. in the windows i usually create my menu handler, i setup the command manager and target, and i create my main component (which is the one that contains all my “children” components… that i can delete in the destructor with deleteAllChildren).

so in the main window i prefer to have only a single component managed by setContentComponent / getContentComponent… in my window destructor i call:

and that’s all.


#12

welldone, thx


#13

…but, how would you proceed to add in such a managed window : some more buttons…

e.g. I constructed a DocWindow with on the top right : solo button, mute buton & so on…
Do you think it is possible to make it belong to the contentComp ?..