On 05.06.2012 09:53, David Currie wrote:
> Many things to say.
>
> Firstly (Albrecht) widget pollenation = the set of all Widgets + child 
> Widgets + operations (add/resize/delete/etc). I used the term in it's context 
> because I was concerned whether FLTK would ALWAYS (generically) CLEAN it's 
> own memory.

Thanks for explanation. Generally there's no way to clean anything
always. If you allocate a widget with operator new, then it's your
responsibility to destroy it as well. There are exceptions, though,
please see below.

FLTK will NOT destroy any static structures it uses internally in a
one-time-for-all way, i.e. structures it has to allocate once and
(probably) retain throughout the program's runtime. However, FLTK
should free all structures it allocates for a widget (or window),
IF this widget or window is destroyed later.

> Also, I have already guessed FWIW = for what it's worth STR = software 
> trouble report,
> AFAICT = as far as I can tell,  FRE = ???

I don't know what FRE could stand for, but maybe it was a typo
for free() ?

>> exit()ing a program calls all destructors first before exiting.
>   I didn't know this although I can't see how (unless C++ runtime has an 
> internal destructor list??).

This is only true for static variables (objects); and yes, the C++
runtime maintains lists of destructors that have to be called (in
the correct, i.e. reverse order) for all static objects.

Stack variables are destroyed when going out of scope (you know
that), and objects created with new MUST be destroyed explicitly.

>>         _exit()ing a program does NOT call the destructors,
>>         but memory is still freed altogether in one big chunk.
>   Certainly.
>
> Now , according to what I understand of C++, and indeed OOP in general
> If class C has a destructor ~C() and you say
>
> C* c = new C();
> ..
> delete c; // C++ calls c->~C() to first destroy c then calls free(c) to 
> release the memory;
>
> Of course if c is a (stack) object (and not a pointer) and goes out of context
> C++ will call ~C() (using its stack address) to destroy c but will NOT call 
> free().

Yup.

> I can certainly ACCEPT the FLTK Style (keeping track internally of FL objects)
> But I would consider this UNUSUAL because when writing C++
>
> A* a = new A();
> B* b = new B();
> C* c = new C();
> a.end();
> ..
> //delete c; // should be allowed to do this
> //delete b; // should be allowed to do this
> delete a;

In fact, this is possible and allowed, and it usually wouldn't do any
harm if you did this in FLTK 1.3 or later. I assume that A, B, and C
are FLTK (widget) classes, and at least A would be derived from
Fl_Group. FLTK's _unusual_ *feature* is that b and c are automatically
add()ed to the open group (a and/or b). This is documented, and you
can say it's an agreement that hands over the responsibility (ownership)
of b and c to their respective parent groups. Hence it is generally NOT
allowed to delete b or c from code other than the widget's methods.

This is why you can't simply delete the text buffer of an
Fl_Text_Display widget w/o telling it that you take over ownership
by removing the buffer.

However, in the case of a, b, and c above, it IS allowed to delete
b and/or c, if you delete c first, since this WILL remove c from its
parent group (in FLTK 1.1 it DID NOT remove it!). However, now it's
easy to see: if class B is also a group, and if b would be deleted
before c, then b would destroy c in its destructor, and then it would
be wrong to destroy c later.

> The very language itself is more than a memory management philosophy,it is a 
> (defined) ENTITLEMENT.

I assume you mean C++ here with "The very language" ? Yes, it is,
and there's no contradiction if you know FLTK's object (widget and
group) design rules.

> Now,it has been asserted when FL::run() returns, the window is closed 
> (hidden) but not destroyed.
>
> I have done some iterative testing using valgrind
>
> #include<FL/Fl.H>
> #include<FL/Fl_Window.H>
> int main() {
>    int lW = 640; int lH = 480; int lCount = 3;
>    while (lCount--)
>    {
>      Fl_Window* lWind = new Fl_Window(lW,lH,"Window");
>      lWind->end();
>      lWind->show(); // this line causes heap to go out
>      delete lWind;
>    }
>    return(0);
> }

If there is a problem with the line mentioned above

   "lWind->show(); // this line causes heap to go out"

then you MIGHT have found a bug. There is some complex work
going on when a window is show()n - on X11 there are more than
one message(s) transmitted and received between the client program
and the X server. Maybe something weird could happen here, because
this is usually done asynchronously only after FLTK has entered
the event loop (Fl::run()). It might be interesting to investigate
this further...

> Valgrind output is
>
> ==7106== Memcheck, a memory error detector
> ==7106== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
> ==7106== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright 
> info
> ==7106== Command: test/demo
> ==7106==
> ==7106==
> ==7106== HEAP SUMMARY:
> ==7106==     in use at exit: 440,808 bytes in 1,080 blocks
> ==7106==   total heap usage: 12,136 allocs, 11,056 frees, 1,723,686 bytes 
> allocated
> ==7106==
> ==7106== LEAK SUMMARY:
> ==7106==    definitely lost: 132 bytes in 2 blocks
> ==7106==    indirectly lost: 29 bytes in 1 blocks
> ==7106==      possibly lost: 0 bytes in 0 blocks
> ==7106==    still reachable: 440,647 bytes in 1,077 blocks
> ==7106==         suppressed: 0 bytes in 0 blocks
> ==7106== Rerun with --leak-check=full to see details of leaked memory
> ==7106==
> ==7106== For counts of detected and suppressed errors, rerun with: -v
> ==7106== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 48 from 9)
>
> I don't know how to interpret these results. Does the ERROR SUMMARY imply NO 
> problems
> or does the LEAK SUMMARY imply PROBLEMS. I wish to test further so please 
> ADVISE.
> (Note I have seen evidence there are definite leaks elsewhere)

Difficult to say. The ERROR SUMMARY looks good ;-), but I don't know
what "suppressed: 48 from 9" would like to tell us.

The LEAK SUMMARY isn't very helpful, since FLTK (and probably no
program at all in the real world) would (try to) release all allocated
memory before exiting. This is really not useful to do - there are
examples that can show a big *unnecessary* slowdown when a program
is stopped due to deleting all objects step-by-step instead of leaving
this to the OS.

What I would try to do is to increase the loop count. Are there
significant differences in the LEAK SUMMARY? If yes (and there is
no other programming error that causes it), then there *could* be
a memory leak that's worth to be investigated.

> Sadly to admit, I have been "creating and deleting windows over and over 
> again"
> in order to (trial and error) calculate the maximum TextX, TextY for a given
> (FL_COURIER)font that will fit EXACTLY to 1 screen.
> Obviously this should be precoded using (some) combination of components
>   ( Fl::w(),Fl::h(),Fl::screen_xywh(X,Y,W,H),
>     Fl_Text_Display::col_to_x(double col), 
> Fl_Text_Display::position_to_xy(int pos,int* x,int* y) ).
> I haven't figured out a workable method yet without first putting a display
>    hence the idea of allowing the user to set their own sizes
>    by "creating and deleting windows over and over again"
>
> So If someone knows how to
> void getMaxWHXY(int&  pW,int&  pH,int&  pX,int&  pY,int pFont)
> // given (FL_COURIER) pFont, calculate pW,pH,pX,pY
> // pW = maxPixelWidth pH = maxPixelHeight pX = maxTextWidth pY = maxTextHeight
> I won't really need to "create and delete windows over and over again".

Firstly, you could resize() the window instead of creating and
deleting the window, but there is an even better method to find the
best font or window size: use fl_measure() to get the width and height
of a particular text, e.g. "MMMMM", and then calculate the font's
character size. This will only work for fixed fonts, but FL_COURIER
is such a font. I'm doing this in my programs too (I'm calculating
a font size that fits into a given window size, using a fixed font
and a given number of columns and lines).

> That said, I still consider this worthy of investigation for the sake of 
> completeness.
>
> I would assume most FLTK users just have one Window(++Widgets...) + lots of 
> callbacks()
> + Fl::run() then exit().
> Maybe this is why no-one has noticed any leaks as they always go out in the 
> wash.

I wrote a program that creates and deletes widgets and windows over
and over again during its runtime, and I never got reports about
increasing memory consumption. However, my program never deletes
windows, since they are reused later, when needed. So this program
creates a small amount (maybe 5 or so) windows that never get deleted,
but all widgets in these windows are created and deleted many times.

> As usual I am just one punter looking for a result. But I am prepared to 
> examine this if allowed.
> Advice?

If you really want to investigate, try to write a program that
leaks memory w/o obvious (user) programming errors, and if you
find one, please post here, so that we can investigate and fix
possible errors. On Windows the task manager can show resources
(you can configure many of them), or maybe sysinternals tools
can even show more infos. Be creative, but keep the program
simple so that we can look at the source code and understand it.

Albrecht
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to