Search code examples
c++oopgtkmm3

Is HelloWindow object deleted?


I created a sample GTKMM project on GNOME Builder. The great thing was that a sample hello world code was automatically generated for my sample project. Since C++ source files are organized into three parts:

  • Header file
  • Implementation file
  • Main file

I've modified my sample code in a single cpp file for demonstration:

#include <iostream>

#include <gtkmm.h>

using std::cout;

using Gtk::Application;
using Gtk::Window;
using Gtk::Box;
using Gtk::Button;
using Gtk::Label;

class HelloWindow : public Window
{
    Box    box;
    Button button;
    Label  label;

public:
    HelloWindow();
    ~HelloWindow();
};

HelloWindow::HelloWindow()
    : Glib::ObjectBase("HelloWindow")
    , Window()
    , box(Gtk::ORIENTATION_VERTICAL)
    , button("Clickable button")
    , label("Hello World!")
{
    set_default_size(320, 240);

    bool expand(true), fill(true);
    box.pack_start(label, expand, fill);
    box.pack_end(button, expand, fill);

    add(box);

    show_all();
}

HelloWindow::~HelloWindow()
{
    cout << "Object successfully destructed!\n";
}

static void
on_activate(Glib::RefPtr<Application> app)
{
    Window *window = app->get_active_window();

    if (not window) {
        window = new HelloWindow();
        window->set_application(app);
        app->add_window(*window);
    }

    window->present();
}

int main()
{
    auto app = Application::create("io.test.window-state-event");

    app->signal_activate().connect(sigc::bind(&on_activate, app));

    return app->run();
}

One interesting part about the above code is that app is connected to on_activate signal which means the user gets to run only one instance of this program. And if he tries to run another instance the previous still running window will instead be presented.

However, there is the use of new keyword on on_activate() and that confuses me a bit. Is the object really deleted when the user closes the HelloWorld window? What I've learnt about C++ new keyword is that one must remember to delete any object allocated with the former keyword.

Moreover, the destructor message "Object successfully destructed!" isn't printed when the window is closed.


Solution

  • Chances are there is an intentional leak, but it's "controlled". The author knows that this method will be called only once. The author also knows the memory needs to be active the entire lifetime of the application. When the application closes, that memory will be freed one way or another (albeit the destructor will never be called, but in this case, there is nothing imperative that would need to be done)

    It's perfectly fine in this scenario.

    If you want to ensure the Window object gets deleted, you could keep a unique_ptr of the Window and it will dispose itself (thanks to @underscore_d comment):

    #include <memory>
    
    static std::unique_ptr<Window> window;
    
    static void
    on_activate(Glib::RefPtr<Application> app)
    {
        if (!window) {
            window = std::make_unique<HelloWindow>();
            window->set_application(app);
            app->add_window(*window);
        }
    
        window->present();
    }
    
    int main()
    {
        auto app = Application::create("io.test.window-state-event");
        app->signal_activate().connect(sigc::bind(&on_activate, app));
        return app->run();
    }
    

    At the end of the day, I am sure the author wanted to keep this "Hello, World" example simple and concise and didn't want to add in some code that doesn't really need to be there in order to keep it simple and concise.