QMdiSubwindow deleted twice in singleton destructor



  • Hi

    I have a singleton class that has a QMdiArea. If I add a new subwindow to it, QMdiArea wants to delete it twice. I have a minimal example here: (I'm calling SharedWindow::instance() at least once).

    // shared_window.h
    #ifndef SHARED_WINDOW_H
    #define SHARED_WINDOW_H
    
    #include <QObject>
    #include <QMdiArea>
    #include <QMdiSubWindow>
    #include <QMainWindow>
    
    class Q_DECL_EXPORT SharedWindow : public QMainWindow
    {
    Q_OBJECT
    
    public:
        ~SharedWindow();
    
        // Singleton
        SharedWindow(SharedWindow const&)   = delete;
        void operator=(SharedWindow const&) = delete;
    
        static SharedWindow &instance(void);
    
    private:
        QMdiArea *mdi;
    
        // Singleton
        SharedWindow();
    };
    
    #endif // SHARED_WINDOW_H
    
    // shared_window.cpp
    #include "shared_window.h"
    
    SharedWindow::SharedWindow()
    {
        this->mdi = new QMdiArea();
        this->setCentralWidget(this->mdi);
        this->mdi->addSubWindow(new QSlider());
        this->show();
    }
    
    SharedWindow::~SharedWindow()
    {
    }
    
    SharedWindow &SharedWindow::instance()
    {
        static SharedWindow i;
    
        return i;
    }
    
    Stack trace:
    
    1  ??                                                    0x7ffff7285cf2 
    2  ??                                                    0x7ffff72886f1 
    3  QMdiSubWindow::~QMdiSubWindow()                       0x7ffff728cd5d 
    4  QMdiSubWindow::~QMdiSubWindow()                       0x7ffff728cd99 
    5  QObjectPrivate::deleteChildren()                      0x7ffff61dcb11 
    6  QWidget::~QWidget()                                   0x7ffff7154d98 
    7  QWidget::~QWidget()                                   0x7ffff7155019 
    8  QObjectPrivate::deleteChildren()                      0x7ffff61dcb11 
    9  QWidget::~QWidget()                                   0x7ffff7154d98 
    10 QMdiArea::~QMdiArea()                                 0x7ffff7278a39 
    11 QObjectPrivate::deleteChildren()                      0x7ffff61dcb11 
    12 QWidget::~QWidget()                                   0x7ffff7154d98 
    13 SharedWindow::~SharedWindow      shared_window.cpp 19 0x7fffe37adffc
    14 __run_exit_handlers                                   0x7ffff4e8fbe8 
    15 exit                                                  0x7ffff4e8fc35 
    16 __libc_start_main                                     0x7ffff4e7a748 
    17 _start                                                0x400e49       
    
    

    Any ideas?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Because it will be deleted by its parent when its parent gets destroyed (see Object Trees & Ownership)

    You should also avoid static QWidget object. They might get created before your QApplication object which should be the first thing created before using any GUI features.

    Out of curiosity, why are you using a singleton to create a QMainWindow ?



  • Hi

    Yes, that's what I was thinking too, but why is it deleted twice then? My QMainWindow is the parent of the QMdiArea, which is the parent of the QMdiSubWindow. And my QMainWindow doesn't have a parent. I'm also never deleting something manually. So why is it segfaulting anyway?

    Would it be better if the QMainWindow was a dynamically allocated member of SharedWindow instead of it's base then?

    I try to create a window that is shared by multiple plugins. They should later be able to (dynamically) push widgets to it. The window itself will also be a plugin, so I can't handle that when the plugins are loaded. A singleton seemed to be the easiest way to have one "global' object.


  • Lifetime Qt Champion

    Since I don't know the rest of your code, I can't comment on that part.

    Technically, it should be the other way around, your application loads the plugins and pulls widgets from them. That will also avoid making a tight coupling between the plugins and your MainWindow class.



  • I got it working! You were right, after some more testing, it turned out, that my class was deleted after QApplication was already deleted. That's what I'm using now:

    // shared_window.h
    #ifndef SHARED_WINDOW_H
    #define SHARED_WINDOW_H
    
    #include <QObject>
    #include <QMdiArea>
    #include <QMdiSubWindow>
    #include <QMainWindow>
    
    class ROBOTCORE_EXPORT SharedWindow : public QObject
    {
    Q_OBJECT
    
    // Singleton
    Q_DISABLE_COPY(SharedWindow)
    
    public:
        ~SharedWindow();
    
        static SharedWindow *instance(void);
    
    private:
        QMdiArea *mdi;
        static SharedWindow *inst;
        QMainWindow *wnd;
    
        // Singleton
        SharedWindow();
    
    private slots:
        void cleanup(void);
    };
    
    #endif // SHARED_WINDOW_H
    
    // shared_window.cpp
    #include "shared_window.h"
    
    SharedWindow *SharedWindow::inst = nullptr;
    
    SharedWindow::SharedWindow()
    {
        this->wnd = new QMainWindow();
        this->mdi = new QMdiArea();
        this->wnd->setCentralWidget(this->mdi);
        this->mdi->addSubWindow(new QSlider());
        this->wnd->show();
    }
    
    void SharedWindow::cleanup()
    {
        delete this->wnd;
    }
    
    SharedWindow::~SharedWindow()
    {
    }
    
    SharedWindow *SharedWindow::instance()
    {
        if(SharedWindow::inst == nullptr)
        {
            SharedWindow::inst = new SharedWindow();
            // Setting qApp as the parent won't do it, don't know why
            connect(QApplication::instance(), &QApplication::aboutToQuit,
                    SharedWindow::inst, &SharedWindow::cleanup);
        }
    
        return SharedWindow::inst;
    }
    
    

    I couldn't delete it from the main application, because I have no control over the main application. Also, my shared window is only used by some specific plugins and isn't part of the main project. The main application has a window of it's own.

    Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.