Newbie: question about destruction of FLTK ojbects

87 views
Skip to first unread message

S ET

unread,
Sep 27, 2026, 6:44:07 AMSep 27
to fltk.general
Hello,

This is my very first step with FLTK and there are certainly many basic things I'm missing about this library.

My concern here is about object destruction.

The following mockup is created with FLUID. I have a added a destructor that is not called at all when the double window closes, with an exit code of 0.
// ---------------------------------------------------------------------------------------------------------------------
// cat blank.h
// generated by Fast Light User Interface Designer (fluid) version 1.0405

#ifndef blank_h
#define blank_h
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>

class UserInterface {
public:
  Fl_Double_Window* make_window();

  // Testing destructor, not added by FLUID.
  virtual ~UserInterface();
};
#endif

// ---------------------------------------------------------------------------------------------------------------------
// cat blank.cpp
// generated by Fast Light User Interface Designer (fluid) version 1.0405

#include "blank.h"

Fl_Double_Window* UserInterface::make_window() {
  Fl_Double_Window* w;
  { Fl_Double_Window* o = new Fl_Double_Window(480, 320);
    w = o; (void)w;
    o->user_data((void*)(this));
    o->end();
  } // Fl_Double_Window* o
  fl_mkdir("/tmp/blank", S_IRUSR | S_IWUSR);
  return w;
}

#include <iostream>
UserInterface::~UserInterface()
{
  // Does not get called!
  std::cout << __FUNCTION__ << std::endl;
  fl_rmdir("/tmp/blank");
}

// ---------------------------------------------------------------------------------------------------------------------
// cat main.cpp
#include "blank.h"

int main(int argc, char * argv[])
{
  UserInterface * ui = new UserInterface();
  Fl_Double_Window * cw = ui->make_window();
 
  cw->show();
  return Fl::run();
}

On application exit, nothing is printed in stdout and the created directory persists. I would have expected the contrary.

I wish to know what's going on, how far is it normal and what should I consider to resolve this.

Using fltk 1.4.5-2 on Arch Linux.

Thank you for any guidance.

Daniel G.

unread,
Sep 27, 2026, 7:36:20 AMSep 27
to fltk.general
Hi,

in C++ if you create objects with the keyword 'new' you need to delete them yourself with 'delete'.

Please learn about RAII and Smart Pointers. Modern concepts which help you avoiding this problem.

Albrecht Schlosser

unread,
Sep 27, 2026, 8:40:39 AMSep 27
to fltkg...@googlegroups.com
On 9/27/26 12:16 S ET wrote:
Hello,

This is my very first step with FLTK and there are certainly many basic things I'm missing about this library.

Welcome to the FLTK world!


My concern here is about object destruction.

OK.


The following mockup is created with FLUID. I have a added a destructor that is not called at all when the double window closes, with an exit code of 0.

[example code elided]


On application exit, nothing is printed in stdout and the created directory persists. I would have expected the contrary.

I wish to know what's going on, how far is it normal and what should I consider to resolve this.

Good.


Using fltk 1.4.5-2 on Arch Linux.

Thank you for any guidance.

FLTK does not delete any widgets by itself, unless they are stack (local) or static objects, but such objects are destroyed by the system (not the library itself) when they go out of scope. All objects created by `new` are kept until exit of the program where their memory is cleaned up by the system (you don't need to care), but they are not `deleted`. This is normal C++ and intentional.

You would only delete FLTK widgets explicitly if they hold resources you need to free at program exit, such as the file opened by your window, or if you frequently add / delete widgets during execution of your program.

The straigt-forward way to do what you want to achieve is to delete the window right after Fl::run(), like this modified code:

  // ... code like before ...
  cw->show();
  int ret = Fl::run();
  delete ui;
  return ret;
}

A better approach would IMHO be to allocate the `ui` instance on the stack so it gets deleted automatically by the system after Fl::run(). Then the destructor of the `ui` can do whatever it needs (as you already wrote in your code).

// cat main.cpp
#include "blank.h"
int main(int argc, char * argv[])
{
UserInterface ui; // note: local (stack) variable
Fl_Double_Window * cw = ui.make_window();
cw->show();
return Fl::run();
}

This works as expected (tested by me).

Note that smart pointers (as Daniel G. suggested) would be another way.

Note also that FLTK *does* automatically delete all *children* of windows (groups) when the window (group) itself is deleted.

Last note: when you close the window by its close button, this calls a callback you may define. If you don't define a callback for the window (as in your code), then the standard callback is to hide (but not delete) the window. Defining a callback for the window would be yet another way to close the file, but I'm not going to post code for this. Feel free to ask if you need more example code.

imm

unread,
Sep 27, 2026, 8:47:57 AMSep 27
to fltkg...@googlegroups.com
On Sun, 27 Sept 2026 at 12:36, Daniel G. <dani.g...@gmail.com> wrote:
>
> in C++ if you create objects with the keyword 'new' you need to delete them yourself with 'delete'.

Well... this is "mostly true", and probably if you were doing this on
a school course the tutor would expect you to delete any object you
new'd...

But in reality, there are some subtleties to this, and that are
pertinent to what FLTK is doing.

Firstly, note that any FLTK widget that is a child of a FLTK container
widget (usually a group or a window, though there are others) will be
cleaned up automatically by FLTK when the container is tidied up.

Secondly, any widget that has a lifetime until the app process
terminates, need not be explicitly deleted, since the OS will
automatically unmap all the app memory on process exit, which in
effect deletes all your widgets "for free". (This process is much
faster than explicitly walking the widget hierarchy and manually
deleting every widget, so is preferred in cases where it is
appropriate - but your school tutor will probably be unhappy about
it!)

This second case may well be what the OP is seeing, since the window
persists until the app exits, at a guess.

Daniel G.

unread,
Sep 27, 2026, 9:42:39 AMSep 27
to fltk.general

> Well... this is "mostly true", and probably if you were doing this on
a school course the tutor would expect you to delete any object you
new'd...

Because it is good practice to take care of the things you own :D If you yield ownership thats a different story.

> Secondly, any widget that has a lifetime until the app process
terminates, need not be explicitly deleted, since the OS will
automatically unmap all the app memory on process exit, which in
effect deletes all your widgets "for free".

But no CTor is called, which can lead to unwanted behaviour (exactly what OP observed). Also I would never fully trust the OS.

Back to OP as a newbie:

Learn about pointers, ownership and object lifetime, RAII etc.!

S ET

unread,
Sep 27, 2026, 9:42:41 AMSep 27
to fltk.general
I got to deleting the main window in a handler, may be it's not the optimal way though:

// ----------------------------------------------------------------------------------------------
static int OnMainWindowEvent(Fl_Widget * w, void * p)
{
  int ev = Fl::event();
 
  switch (ev)
  {
    case FL_CLOSE:
      delete w;
      return 0; // 0 or 1 ?
    default:
      std::cout << "Main window event: " << ev << std::endl;
      break;
  }
 
  return 1;
}
// ----------------------------------------------------------------------------------------------

I am happy to read the many more options you have listed;

and to note the reactivity of the forum.

So many more subtleties to discover yet.

Thank you all and regards.

P.S: I'm not that unfamiliar to C++, just coming from other worlds

imm

unread,
Sep 27, 2026, 10:06:08 AMSep 27
to fltkg...@googlegroups.com
On Sun, 27 Sept 2026 at 14:42, Daniel G. wrote:
>
>
> > Well... this is "mostly true", and probably if you were doing this on
> a school course the tutor would expect you to delete any object you
> new'd...
>
> Because it is good practice to take care of the things you own :D If you yield ownership thats a different story.

Hi Daniel,

Well... it does kinda depend, really...
(Here's comes a warstory I've posted before... sorry...)

Years ago, I was working on a complex app. A new start was assigned to
our team, and as part of his on-boarding he was tasked with cleaning
up a load of papercuts and issues in the code base; a good way to get
familiar with it all.
As he was going along, being fresh out of school, he added explicit
destructors for all the "lifetime" objects (which we had deliberately
NOT destroyed explicitly.)

The upshot was that the app went from terminating "instantly" on exit,
to taking 2 or 3 minutes.
We got A LOT of user complaints.
He was made to go back and remove 'em all...

Note that we knew (valgrind et all) that we were not leaking memory,
or indeed any other resources.

>
> > Secondly, any widget that has a lifetime until the app process
> terminates, need not be explicitly deleted, since the OS will
> automatically unmap all the app memory on process exit, which in
> effect deletes all your widgets "for free".
>
> But no CTor is called, which can lead to unwanted behaviour (exactly what OP observed). Also I would never fully trust the OS.

Only if the object holds some resource that can't or won't be freed by
the OS on process termination, e.g. a file handle or similar, say, or
if you depend on the destructor being called to perform some other
action(s) on object termination.
That does not apply to any stock FLTK widget - the OS will always
unmap the memory resources, and FLTK widgets don't really hold
anything else that "must" be done when the app terminates.
So in the OPs case, I don't think this will be an issue.

If you derive your own widget, and it holds any non-memory resource,
then you DO need to ensure it is released, but memory only objects,
it's fine, always.
I do not know any OS where this does not work, even the hack toy OS's
that I've written do this correctly!

Albrecht Schlosser

unread,
Sep 27, 2026, 10:08:37 AMSep 27
to fltkg...@googlegroups.com
On 9/27/26 15:40 S ET wrote:
I got to deleting the main window in a handler, may be it's not the optimal way though:

// ----------------------------------------------------------------------------------------------
static int OnMainWindowEvent(Fl_Widget * w, void * p)
{
  int ev = Fl::event();
 
  switch (ev)
  {
    case FL_CLOSE:
      delete w;
      return 0; // 0 or 1 ?
    default:
      std::cout << "Main window event: " << ev << std::endl;
      break;
  }
 
  return 1;
}
// ----------------------------------------------------------------------------------------------

Unfortunately you didn't write how you established (registered) this "handler". Its signature looks like a callback of a widget. Since you are using `delete w` I assume that it's established like:

  cw->callback(OnMainWindowEvent, ...);

Hence this would call the callback when the window is closed by its close button. There's no need to check for the recent event by calling `Fl::event();` - did you ever see the output of `"Main window event: " << ev << ...` ?

However, a callback would be a `void` function, i.e. it would return nothing. There are other real handler() methods which are called from event handling that must return 0 or 1, depending on whether you used (consumed) the event. But these can only be defined if you subclass another widget class.

Last but not least, this handler would delete the window object, which is - as Ian and I said - not necessary, but it doesn't remove your directory, does it?


I am happy to read the many more options you have listed;

and to note the reactivity of the forum.

So many more subtleties to discover yet.

Thank you all and regards.

Welcome. There is indeed much more to discover. If you want to learn more about FLTK, reading the first chapters of the documentation, which are kinda tutorials, is strongly recommended. There are also a lot of test and example programs bundled with the FLTK library in these folders:
  • /examples/ : these attempt to provide short programs with good coding practices to new users
  • /test/ : all kinds of test and demo programs to test the FLTK library itself. The code in these programs works but may not be the recommended practice for user programs. It's a valuable resource for learning FLTK though.

Have fun with FLTK!


S ET

unread,
Sep 27, 2026, 10:45:22 AMSep 27
to fltk.general
> cw->callback(OnMainWindowEvent, ...);

That's exactly it.

> but it doesn't remove your directory, does it?

No indeed. But in the real tiny app I'm working on, it's not UserInterface as in the mockup that is created from main, but a derived class of UserInterface, because the latter will always be modified by FLUID. Surprisingly after your comment and noting that you are right, the files that are created by the real app do disappear on exit with 'delete w', being explicitly removed in downwards destructors. They were not being removed without this handler. I'll still have to figure out why in this case, and not in the mockup.

> There is indeed much more to discover.
> Have fun with FLTK!

Yep, that's one of the many goals.

Thank you all.

Albrecht Schlosser

unread,
Sep 27, 2026, 11:03:28 AMSep 27
to fltkg...@googlegroups.com
On 9/27/26 16:45 S ET wrote:
> cw->callback(OnMainWindowEvent, ...);

That's exactly it.

OK, but this code needs compiler flag `-fpermissive`, and even with that it still issues a warning. changing `int OnMainWindowEvent` to `void OnMainWindowEvent` is correct and fixes the warning.


> but it doesn't remove your directory, does it?

No indeed. But in the real tiny app I'm working on, it's not UserInterface as in the mockup that is created from main, but a derived class of UserInterface, because the latter will always be modified by FLUID. Surprisingly after your comment and noting that you are right, the files that are created by the real app do disappear on exit with 'delete w', being explicitly removed in downwards destructors. They were not being removed without this handler. I'll still have to figure out why in this case, and not in the mockup.

Well, good luck with that.

FYI - to answer my own question: `did you ever see the output of "Main window event: " << ev << ... ?`:

It is possible to see this message with the given code (established as a callback) if the user tries to close the main window by typing `Esc`. In this case the recent event is FL_SHORTCUT (12). To test this, add

#include <FL/names.h>
and use this modified callback:

static void OnMainWindowEvent(Fl_Widget * w, void * p)
{
int ev = Fl::event();
switch (ev)
{
case FL_CLOSE:
delete w;
break;
default:
std::cout << "Main window event: " << fl_eventnames[ev] << std::endl;
break;
}
}

Then press `Esc` (Escape) when running the program. `fl_eventnames[int ev]` is a nice way to decode event numbers.

I think that `Esc` is the only way to trigger the callback with an event other than FL_CLOSE. Checking for this event can be used to prevent the user from closing the window with `Esc` which is documented somewhere (I don't recall where exactly).

Enjoy!
Reply all
Reply to author
Forward
0 new messages