Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Solved QMdiSubwindow deleted twice in singleton destructor

    General and Desktop
    qmdiarea qmdisubwindow
    2
    5
    1404
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Shadowigor
      Shadowigor last edited by

      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?

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        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 ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • Shadowigor
          Shadowigor last edited by

          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.

          1 Reply Last reply Reply Quote 0
          • SGaist
            SGaist Lifetime Qt Champion last edited by

            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.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply Reply Quote 0
            • Shadowigor
              Shadowigor last edited by

              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!

              1 Reply Last reply Reply Quote 0
              • First post
                Last post