How to end an application properly when using custom classes ?

121 views
Skip to first unread message

Lucas Sanner

unread,
May 28, 2023, 2:48:43 AM5/28/23
to fltk.general
Hi all,
I'm a bit confused regarding what to do with destructors when a custom class is interacting with a FLTK application.
Here's a super simple example to illustrate my problem:  

myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H

class Myclass
{
    int *pInt;

    public:

        Myclass()
        {  
            printf("Myclass Constructor\n");
            pInt = new int;
        }  

        ~Myclass()
        {  
            printf("Myclass Destructor\n");
            delete pInt;
        }  

        int* getPInt() { return pInt; }
};

#endif


main.h

#ifndef MAIN_H
#define MAIN_H
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include "myclass.h"

class Application : public Fl_Double_Window
{
      Myclass *myClass;

    public:

       Application(int w, int h, const char *l, int argc, char *argv[]);

};

#endif


main.cpp

#include "main.h"

Application::Application(int w, int h, const char *l, int argc, char *argv[]) : Fl_Double_Window(w, h, l)
{
    myClass = new Myclass;
    resizable(this);
    show();
}

int main(int argc, char *argv[])
{
    Application *app = new Application(300,200,"My Application", argc, argv);
    return Fl::run();
}


What confuses me is the printf message into the destructor is not dispayed when I quit the application.
So I tried to add a destructor to the Application class:

~Application()
{
   delete myClass;
}

but the printf message is not displayed either after the application is closed.
What should I do to make the application end properly ?

Albrecht Schlosser

unread,
May 28, 2023, 5:49:59 AM5/28/23
to fltkg...@googlegroups.com
On 5/28/23 08:48 Lucas Sanner wrote:
Hi all,
I'm a bit confused regarding what to do with destructors when a custom class is interacting with a FLTK application.
Here's a super simple example to illustrate my problem: 

[most of example code elided]


int main(int argc, char *argv[])
{
    Application *app = new Application(300,200,"My Application", argc, argv);
    return Fl::run();
}


What confuses me is the printf message into the destructor is not dispayed when I quit the application.
So I tried to add a destructor to the Application class:

~Application()
{
   delete myClass;
}

but the printf message is not displayed either after the application is closed.

First of all, there's nothing that would make your Application class call its destructor. This is much more a C++ question than an FLTK question, but anyway...

If you changed your main to instantiate your Application class as a local object rather than on the heap (as your example does), then the system would also call its destructor on exit, like this:

  Application app(300,200,"My Application", argc, argv);
  return Fl::run();

What should I do to make the application end properly ?

Well, that's an entirely different question. Do you really need a destructor to be executed? Your simple example definitely doesn't need it because the destructor wouldn't do anything the system doesn't do anyway at exit of the program (e.g. free all allocated memory).

However, a more involved program might indeed need a destructor to free used resources, or to write out buffered data to a file, or whatever. In such a case you could either do as described above, or you can add a callback to your main window (i.e. Application) that is called when the user closes the window with the window close button. Or you add a quit button that calls a callback and then deletes all objects that need their destructors to be executed.

Example (untested):

void close_cb(Fl_Widget *w, void *v) {
  delete w;

}

int main(int argc, char *argv[])
{
    Application *app = new Application(300,200,"My Application", argc, argv);
    app->callback(close_cb);
    return Fl::run();
}

Note that the callback `close_cb` is very terse. When it's called the user requested the window to be closed, and `Fl_Widget *w` is a pointer to your Application class. You could cast it to `Application*` but this is not necessary. The delete operator will delete the Application, i.e. the base class Fl_Double_Window which will close the window and delete its Fl_Double_Window instance.

Note also that you may not *see* the output on Windows, particularly if built with Visual Studio, because such output on stdout would be suppressed by the Windows (VS) runtime system - but you didn't mention on which platform you are working.

Lucas Sanner

unread,
May 28, 2023, 12:23:17 PM5/28/23
to fltk.general
Thanks for clarifying.


"but you didn't mention on which platform you are working."
I'm under Ubuntu 22.04 and I'm using Vim with gcc compiler.

Albrecht Schlosser

unread,
May 28, 2023, 12:31:35 PM5/28/23
to fltkg...@googlegroups.com
On 5/28/23 18:23 Lucas Sanner wrote:
> Thanks for clarifying.

Welcome.

> "but you didn't mention on which platform you are working."
> I'm under Ubuntu 22.04 and I'm using Vim with gcc compiler.

OK, then you should see printf() output to stdout.

BTW, another thing you can do is not to return directly after Fl::run()
but add whatever you need there. Fl::run() returns when all windows are
closed which is the time for cleanup before exiting the program, e.g.

  int ret = Fl::run();
  // add cleanup code here
  return ret;

But be aware that it is often not necessary to delete all allocated
objects. It can slow down the program rundown significantly for no effect.

Lucas Sanner

unread,
May 29, 2023, 2:39:58 AM5/29/23
to fltk.general
> OK, then you should see printf() output to stdout.

Yes I do, but provided I call the Application destructor:
~Application()
{
   delete myClass;
}

So it goes to show that memory dynamically allocated by a custom class has to be freed explicitly, if I understand correctly.
Pardon my confusion and correct me if I'm wrong.

Ian MacArthur

unread,
May 29, 2023, 3:48:32 AM5/29/23
to fltk.general
On Monday, 29 May 2023 at 07:39:58 UTC+1 lucas wrote:

So it goes to show that memory dynamically allocated by a custom class has to be freed explicitly, if I understand correctly.
Pardon my confusion and correct me if I'm wrong.

Well...

I think this is, at core, more of a C++ question than a fltk one, but *in general* a fltk class will be deleted when its parent container class is deleted - most fltk containers (typically group or window classes) will delete their own children when they are deleted. And, in general, this will apply to derived classes also.

However... the next thing to consider is *when* you are deleting the object. An object that persists for the life time of the application may not be worth deleting at all.
In general, calling the destructors for C++ objects is slower (sometimes very much slower) than simply letting process termination release all the memory automatically on process exit.

So if your objects are "memory only", and they persist for the lifetime of the process, then all the memory they hold will be released by process termination, and this will happen faster and more efficiently than you can do it by triggering the destructors.
So a lot of fltk code just allows the fltk objects to be reaped by process termination (without calling the destructors) if they persist for the lifetime of the application - which, I imagine, is the effect you are seeing.

Objects that hold other resources (other than "plain memory") such as file handles or sockets or so forth, probably should be explicitly deleted, but only if the destructors for those objects are responsible for clearing up such resources. (And in any case you need to make sure those resources are properly released.)

Objects that are created and released dynamically as the application runs are another matter - in that case, you need to consider their lifetimes and usage and decide whether they represent a potential leak of resources (and hence should be explicitly deleted) or not, and program accordingly.

C and C++ are just like that - you need to manage the memory yourself, and it is a constant source of issues...



Albrecht Schlosser

unread,
May 29, 2023, 5:03:45 AM5/29/23
to fltkg...@googlegroups.com
On 5/29/23 08:39 Lucas Sanner wrote:
> > OK, then you should see printf() output to stdout.
>
> Yes I do, but provided I call the Application destructor:
> ~Application()
> {
>    delete myClass;
> }

Sure. I wanted to emphasize that you would see printf output on Linux
and other OS's whereas Windows (particularly Visual Studio builds) would
*suppress* the output even *if* you called the destructor.

> So it goes to show that memory dynamically allocated by a custom class
> has to be freed explicitly, if I understand correctly.

As Ian wrote... (see his reply).

The issue lies in the wording "memory dynamically allocated" and not in
"custom class" or not (as opposed to FLTK classes if that's what you
mean). If we define "dynamically allocated" as "allocated by operator
new" then such objects must be deleted explicitly, but as Ian explained
FLTK will do this for you for all children of container widgets if/when
their parent widgets are deleted. Your "Application" class is the main
window, i.e. the parent of all other widgets, and will therefore not be
deleted automatically, unless ...

Here comes the C++ automatism into play: if you allocate a widget on the
stack (as local variable) rather than with 'new' it will be deleted by
the C++ runtime as soon as the object goes out of scope. This is the
difference I mentioned in my first reply and has nothing to do
specifically with FLTK, it's a C++ property.

Lucas Sanner

unread,
May 29, 2023, 5:33:24 AM5/29/23
to fltk.general
Ok, I think I've got it now.
Thank you guys for taking time to explain this matter in detail.
Reply all
Reply to author
Forward
0 new messages