Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Seg fault when deleting Q3DScatter object
QtWS25 Last Chance

Seg fault when deleting Q3DScatter object

Scheduled Pinned Locked Moved Unsolved General and Desktop
q3dscattersegmentationsegfault
15 Posts 4 Posters 2.3k Views
  • 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.
  • V Offline
    V Offline
    vedranMv
    wrote on 24 Oct 2020, 20:40 last edited by vedranMv
    #1

    Hello,

    I've been working on an app that can visualize data using different QT objects which are created on runtime. Something like this:
    894dbb8b-9fad-481a-bcc5-fef8f5c812a8-image.png

    The idea is that you can spawn different types of plots inside the MDI area, connect them to data sources and plot data in real time.
    The picture here shows two of the available plots: 3D orientation (based on a QT examples), and a scatter plot (also based on QT example). Now, if I only ever spawn 3D orientation windows (say 5 windows with the cube), then try to close them - all works great. Same goes for scatter plots, I can spawn and close as many of them as I like.

    The problem appear when I use both plots at the same (like in the picture above). Namely, if the orientation and scatter plot are open, and I try to close scatter plot, I get segmentation fault (but not the other way around). I have tried several things listed below but the bottom line seems to be that when both objects exist, I'm unable destroy Q3DScatter without segfault:

    • Both MDI windows created (as per code below), set to delete on close. Delete scatter plot and call 'deleteLater' on Q3DScatter object
    • Both MDI windows created (as per code below), set to delete on close. Delete scatter plot and omit calling 'deleteLater' on Q3DScatter object (I assume UI does that in such case)
    • Create scatter plot in QDialog (outside of main window and MDI area), while orientation widget is open in MDI area in UI. QDialog is set to delete on close. Closing QDialog window crashes main window with segfault

    I am developing on Windows10 and I tried compiling with both MinGW and MSVC2019, behavior is consistent. At this point, I'm getting pretty desperate and I'm hoping somebody can point towards something obvious I'm missing here.


    Creation of windows (essentially copied from the example, with my header window):

    void MainWindow::on_add3D_clicked()
    {
        static uint8_t _3DgraphCount = 0;
        QWidget *orient3DWindow = new QWidget();
        OrientationWidget *tmp = new OrientationWidget();
    
        QVBoxLayout *windMainLayout = new QVBoxLayout();
        orient3DWindow->setLayout(windMainLayout);
    
        graphHeaderWidget *header = new graphHeaderWidget(3, false);
        windMainLayout->addLayout(header->GetLayout());
        windMainLayout->addWidget(tmp);
    
        //  Make sure input channel dropdowns have updated list of channels
        QObject::connect(mux,
                         &DataMultiplexer::ChannelsUpdated,
                         header,
                         &graphHeaderWidget::UpdateChannelDropdown);
        //  Handle dynamic channel selection by dropdown
        QObject::connect(header, &graphHeaderWidget::UpdateInputChannels,
                         tmp, &OrientationWidget::UpdateInputChannels);
    
        tmp->setMinimumSize(QSize(200,200));
        tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    
        ui->mdiArea->addSubWindow(orient3DWindow);
        tmp->parentWidget()->setWindowFlags(Qt::WindowCloseButtonHint);
        tmp->parentWidget()->setAttribute(Qt::WA_DeleteOnClose, true);
        tmp->parentWidget()->setWindowTitle("3D Orientation " + QString::number(_3DgraphCount));
    
        mux->RegisterGraph("3D Orientation " + QString::number(_3DgraphCount), 3, tmp);
    
        tmp->parentWidget()->show();
        _3DgraphCount++;
    }
    
    void MainWindow::on_addScatter_clicked()
    {
        static uint8_t _ScatterCount = 0;
        QString winID = QString::number(_ScatterCount);
    
        //  Create scatter plot
        ScatterPlot *scatterWindow = new ScatterPlot ();
    
        ui->mdiArea->addSubWindow(scatterWindow->WindowContainer());
        scatterWindow->WindowContainer()->parentWidget()->setWindowFlags(Qt::WindowCloseButtonHint);
        scatterWindow->WindowContainer()->parentWidget()->setAttribute(Qt::WA_DeleteOnClose, true);
        scatterWindow->WindowContainer()->parentWidget()->setWindowTitle("Scatter " + winID);
    
        mux->RegisterGraph("Scatter " + QString::number(_ScatterCount), 3, scatterWindow);
    
        scatterWindow->WindowContainer()->parentWidget()->show();
    
        _ScatterCount++;
    }
    
    

    Scatter plot constructor

    ScatterPlot ::ScatterPlot ()
        : m_fontSize(40.0f),
          m_style(QAbstract3DSeries::MeshPoint),
          m_itemCount(lowerNumberOfItems),
          m_curveDivider(lowerCurveDivider)
    {
        m_graph = new Q3DScatter();
    
        _contWind = new QWidget();
    
        //  Main vertical layout
        QVBoxLayout *windMainLayout = new QVBoxLayout(_contWind);
    
        graphHeaderWidget *header = new graphHeaderWidget(3, false);
        windMainLayout->addLayout(header->GetLayout());
        //  Create container window and set size policy
        QWidget *graphCont = QWidget::createWindowContainer(m_graph);
        graphCont->setMinimumSize(QSize(200,200));
        graphCont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        windMainLayout->addWidget(graphCont,1);
    }
    

    GDB output:
    ac26a9d9-9197-4f99-b066-eec3ad243d58-image.png

    J 1 Reply Last reply 24 Oct 2020, 22:17
    0
    • V vedranMv
      24 Oct 2020, 20:40

      Hello,

      I've been working on an app that can visualize data using different QT objects which are created on runtime. Something like this:
      894dbb8b-9fad-481a-bcc5-fef8f5c812a8-image.png

      The idea is that you can spawn different types of plots inside the MDI area, connect them to data sources and plot data in real time.
      The picture here shows two of the available plots: 3D orientation (based on a QT examples), and a scatter plot (also based on QT example). Now, if I only ever spawn 3D orientation windows (say 5 windows with the cube), then try to close them - all works great. Same goes for scatter plots, I can spawn and close as many of them as I like.

      The problem appear when I use both plots at the same (like in the picture above). Namely, if the orientation and scatter plot are open, and I try to close scatter plot, I get segmentation fault (but not the other way around). I have tried several things listed below but the bottom line seems to be that when both objects exist, I'm unable destroy Q3DScatter without segfault:

      • Both MDI windows created (as per code below), set to delete on close. Delete scatter plot and call 'deleteLater' on Q3DScatter object
      • Both MDI windows created (as per code below), set to delete on close. Delete scatter plot and omit calling 'deleteLater' on Q3DScatter object (I assume UI does that in such case)
      • Create scatter plot in QDialog (outside of main window and MDI area), while orientation widget is open in MDI area in UI. QDialog is set to delete on close. Closing QDialog window crashes main window with segfault

      I am developing on Windows10 and I tried compiling with both MinGW and MSVC2019, behavior is consistent. At this point, I'm getting pretty desperate and I'm hoping somebody can point towards something obvious I'm missing here.


      Creation of windows (essentially copied from the example, with my header window):

      void MainWindow::on_add3D_clicked()
      {
          static uint8_t _3DgraphCount = 0;
          QWidget *orient3DWindow = new QWidget();
          OrientationWidget *tmp = new OrientationWidget();
      
          QVBoxLayout *windMainLayout = new QVBoxLayout();
          orient3DWindow->setLayout(windMainLayout);
      
          graphHeaderWidget *header = new graphHeaderWidget(3, false);
          windMainLayout->addLayout(header->GetLayout());
          windMainLayout->addWidget(tmp);
      
          //  Make sure input channel dropdowns have updated list of channels
          QObject::connect(mux,
                           &DataMultiplexer::ChannelsUpdated,
                           header,
                           &graphHeaderWidget::UpdateChannelDropdown);
          //  Handle dynamic channel selection by dropdown
          QObject::connect(header, &graphHeaderWidget::UpdateInputChannels,
                           tmp, &OrientationWidget::UpdateInputChannels);
      
          tmp->setMinimumSize(QSize(200,200));
          tmp->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      
          ui->mdiArea->addSubWindow(orient3DWindow);
          tmp->parentWidget()->setWindowFlags(Qt::WindowCloseButtonHint);
          tmp->parentWidget()->setAttribute(Qt::WA_DeleteOnClose, true);
          tmp->parentWidget()->setWindowTitle("3D Orientation " + QString::number(_3DgraphCount));
      
          mux->RegisterGraph("3D Orientation " + QString::number(_3DgraphCount), 3, tmp);
      
          tmp->parentWidget()->show();
          _3DgraphCount++;
      }
      
      void MainWindow::on_addScatter_clicked()
      {
          static uint8_t _ScatterCount = 0;
          QString winID = QString::number(_ScatterCount);
      
          //  Create scatter plot
          ScatterPlot *scatterWindow = new ScatterPlot ();
      
          ui->mdiArea->addSubWindow(scatterWindow->WindowContainer());
          scatterWindow->WindowContainer()->parentWidget()->setWindowFlags(Qt::WindowCloseButtonHint);
          scatterWindow->WindowContainer()->parentWidget()->setAttribute(Qt::WA_DeleteOnClose, true);
          scatterWindow->WindowContainer()->parentWidget()->setWindowTitle("Scatter " + winID);
      
          mux->RegisterGraph("Scatter " + QString::number(_ScatterCount), 3, scatterWindow);
      
          scatterWindow->WindowContainer()->parentWidget()->show();
      
          _ScatterCount++;
      }
      
      

      Scatter plot constructor

      ScatterPlot ::ScatterPlot ()
          : m_fontSize(40.0f),
            m_style(QAbstract3DSeries::MeshPoint),
            m_itemCount(lowerNumberOfItems),
            m_curveDivider(lowerCurveDivider)
      {
          m_graph = new Q3DScatter();
      
          _contWind = new QWidget();
      
          //  Main vertical layout
          QVBoxLayout *windMainLayout = new QVBoxLayout(_contWind);
      
          graphHeaderWidget *header = new graphHeaderWidget(3, false);
          windMainLayout->addLayout(header->GetLayout());
          //  Create container window and set size policy
          QWidget *graphCont = QWidget::createWindowContainer(m_graph);
          graphCont->setMinimumSize(QSize(200,200));
          graphCont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
          windMainLayout->addWidget(graphCont,1);
      }
      

      GDB output:
      ac26a9d9-9197-4f99-b066-eec3ad243d58-image.png

      J Offline
      J Offline
      JonB
      wrote on 24 Oct 2020, 22:17 last edited by JonB
      #2

      @vedranMv
      I am not familiar with Windows/MinGW. But if you run this in a debugger don't you get a stack trace when the SIGSEGV is generated? Like the gdb bt command? Or in VS for MSVC?

      1 Reply Last reply
      0
      • V Offline
        V Offline
        vedranMv
        wrote on 24 Oct 2020, 22:55 last edited by
        #3

        Thank you for a reply, I am familiar with gdb stack trace and was hoping to see it, but at the time of the crash, textual log doesn't contain anything that resembles it, and even stack in QT is empty. But it might not be enabled by default, and I can't find a way to enable it.

        I look into getting a stack trace from gdb

        J 1 Reply Last reply 25 Oct 2020, 08:17
        0
        • V vedranMv
          24 Oct 2020, 22:55

          Thank you for a reply, I am familiar with gdb stack trace and was hoping to see it, but at the time of the crash, textual log doesn't contain anything that resembles it, and even stack in QT is empty. But it might not be enabled by default, and I can't find a way to enable it.

          I look into getting a stack trace from gdb

          J Offline
          J Offline
          JonB
          wrote on 25 Oct 2020, 08:17 last edited by
          #4

          @vedranMv
          I am not used to seeing anything like the textual output you show when running/debugging inside Qt Creator. Is that what you are doing? Normally then the Creator debugger windows handle all of this, you don't need to look at "gdb output".

          and even stack in QT is empty

          Show screenshot of what you mean here?

          V 1 Reply Last reply 25 Oct 2020, 09:25
          0
          • J JonB
            25 Oct 2020, 08:17

            @vedranMv
            I am not used to seeing anything like the textual output you show when running/debugging inside Qt Creator. Is that what you are doing? Normally then the Creator debugger windows handle all of this, you don't need to look at "gdb output".

            and even stack in QT is empty

            Show screenshot of what you mean here?

            V Offline
            V Offline
            vedranMv
            wrote on 25 Oct 2020, 09:25 last edited by
            #5

            @JonB Yes, I simply press on the debug button inside QT creator. The view looks something like:
            ac6271f3-314a-45fa-a7e3-873d191764d4-image.png
            I might've pressed something to add the two windows with textual output on top. If I remember correctly they were not there by default.
            Blue arrow shows what I refer to as "QT stack being empty". I'm used to seeing a call stack in here, but when the issue happens, it shows '??'

            J 1 Reply Last reply 25 Oct 2020, 11:24
            0
            • V vedranMv
              25 Oct 2020, 09:25

              @JonB Yes, I simply press on the debug button inside QT creator. The view looks something like:
              ac6271f3-314a-45fa-a7e3-873d191764d4-image.png
              I might've pressed something to add the two windows with textual output on top. If I remember correctly they were not there by default.
              Blue arrow shows what I refer to as "QT stack being empty". I'm used to seeing a call stack in here, but when the issue happens, it shows '??'

              J Offline
              J Offline
              JonB
              wrote on 25 Oct 2020, 11:24 last edited by JonB
              #6

              @vedranMv
              Why are you in the Disassembler pane? I think use the up/down arrows there to pick the "stack trace" pane? Find & show that, even if it turns out the stack is corrupted (which can happen), at least let's see the appropriate pane. I don't recognise your layout/the top pane, but then I am Qt Creator/gdb/gcc under Linux.

              V 1 Reply Last reply 25 Oct 2020, 13:10
              0
              • J JonB
                25 Oct 2020, 11:24

                @vedranMv
                Why are you in the Disassembler pane? I think use the up/down arrows there to pick the "stack trace" pane? Find & show that, even if it turns out the stack is corrupted (which can happen), at least let's see the appropriate pane. I don't recognise your layout/the top pane, but then I am Qt Creator/gdb/gcc under Linux.

                V Offline
                V Offline
                vedranMv
                wrote on 25 Oct 2020, 13:10 last edited by
                #7

                @JonB Thanks for suggestion. That's where I'm taken when fault happens. I guess it means that fault is thrown in some of the libraries, which can't be tracked? If I use the left/right arrows, I get taken back to another dissasembly screen when pressing left arrow for the first time, then back to whatever document I edited the last, when pressed for the second time.

                I have been playing with destructor of ScatterPlot class. If I leave it empty or make it like this, I get seg fault:

                ScatterPlot ::~ScatterPlot ()
                {
                      m_graph->seriesList().clear();
                      m_graph->close();
                      m_graph->deleteLater();
                }
                

                If I instead directly call m_graph's destructor, seg fault is not happening.

                ScatterPlot ::~ScatterPlot ()
                {
                      m_graph->seriesList().clear();
                      m_graph->close();
                      m_graph->~Q3DScatter();
                }
                
                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 25 Oct 2020, 16:27 last edited by
                  #8

                  Hi,

                  Might be a silly question but are you sure you are using a debug build ?

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

                  V 1 Reply Last reply 25 Oct 2020, 19:05
                  0
                  • S SGaist
                    25 Oct 2020, 16:27

                    Hi,

                    Might be a silly question but are you sure you are using a debug build ?

                    V Offline
                    V Offline
                    vedranMv
                    wrote on 25 Oct 2020, 19:05 last edited by
                    #9

                    @SGaist Thanks, I don't mind revisiting the basics :) I am running a debug build and if I force a fault in my part of the code, I get output as expected with a fault point in code and stack trace underneath

                    45e5d7df-ea90-4831-8ef3-dfd0f875ea6b-image.png

                    J 1 Reply Last reply 26 Oct 2020, 09:18
                    0
                    • V vedranMv
                      25 Oct 2020, 19:05

                      @SGaist Thanks, I don't mind revisiting the basics :) I am running a debug build and if I force a fault in my part of the code, I get output as expected with a fault point in code and stack trace underneath

                      45e5d7df-ea90-4831-8ef3-dfd0f875ea6b-image.png

                      J Offline
                      J Offline
                      JonB
                      wrote on 26 Oct 2020, 09:18 last edited by
                      #10

                      @vedranMv
                      So now you do have the stack trace pane which you said you couldn't get at!

                      It's dumping inside QComboBox::currentText(). For SIGSEGV I would check in debugger what your *X is, taken from your inCh, for validity.

                      V 1 Reply Last reply 26 Oct 2020, 15:51
                      0
                      • J JonB
                        26 Oct 2020, 09:18

                        @vedranMv
                        So now you do have the stack trace pane which you said you couldn't get at!

                        It's dumping inside QComboBox::currentText(). For SIGSEGV I would check in debugger what your *X is, taken from your inCh, for validity.

                        V Offline
                        V Offline
                        vedranMv
                        wrote on 26 Oct 2020, 15:51 last edited by
                        #11

                        @JonB No, this is an example to show that normally I am able to see the stack trace. This was provoked on purpose. But thanks :)

                        When the original segfault happens, this window remains empty as shown above

                        1 Reply Last reply
                        1
                        • V Offline
                          V Offline
                          vedranMv
                          wrote on 26 Oct 2020, 21:30 last edited by vedranMv
                          #12

                          I have uploaded the code to github, in case anybody is interested in trying it out: https://github.com/vedranMv/dataDashboard/

                          There's a branch called segfault which in combination with the description above creates the fault. To recap, steps are:

                          1. Run the app
                          2. In the Dashboard tab press "Add 3D" button
                          3. In the Dashboard tab press "Add scatter" button
                          4. Press 'X' to close scatter window
                          5. Enjoy the segfault

                          There's also what I believe is a fix, but I'd like to understand why it works. Documentation and general recommendation is to use deleteLater() instead, but that also results in a segfault :)
                          156ef785-bcd3-48e5-a037-c864f4afda61-image.png

                          1 Reply Last reply
                          0
                          • J Offline
                            J Offline
                            JohanSolo
                            wrote on 27 Oct 2020, 06:59 last edited by JohanSolo
                            #13

                            Ouch, that hurts! Why do you explicitly call the destructor?
                            If you do want to free the memory (and do you?) use delete _graph. Did you set a parent to your Q3DScatter instance? If you did, then it will be deleted for you.

                            Edit:
                            @vedranMv said in Seg fault when deleting Q3DScatter object:

                            There's also what I believe is a fix, but I'd like to understand why it works. Documentation and general recommendation is to use deleteLater() instead, but that also results in a segfault :)

                            Then it means you're most probably deleting twice the instance: the first time with your dicey call to the destructor / or deleteLater, and the second when the parent object gets deleted.

                            `They did not know it was impossible, so they did it.'
                            -- Mark Twain

                            V 1 Reply Last reply 27 Oct 2020, 08:29
                            2
                            • J JohanSolo
                              27 Oct 2020, 06:59

                              Ouch, that hurts! Why do you explicitly call the destructor?
                              If you do want to free the memory (and do you?) use delete _graph. Did you set a parent to your Q3DScatter instance? If you did, then it will be deleted for you.

                              Edit:
                              @vedranMv said in Seg fault when deleting Q3DScatter object:

                              There's also what I believe is a fix, but I'd like to understand why it works. Documentation and general recommendation is to use deleteLater() instead, but that also results in a segfault :)

                              Then it means you're most probably deleting twice the instance: the first time with your dicey call to the destructor / or deleteLater, and the second when the parent object gets deleted.

                              V Offline
                              V Offline
                              vedranMv
                              wrote on 27 Oct 2020, 08:29 last edited by
                              #14

                              @JohanSolo Thanks, I for some reason did not think of using delete here at all :D That works just as good!

                              Regarding your edit, what you're writing makes perfect sense, but as you can see in the code, it's the other way around. If I don't call delete manually, I get a segfault. And yes, object gets a parent because I encapsulate it into a container widget, which is then added into the UI window.

                              J 1 Reply Last reply 27 Oct 2020, 08:32
                              0
                              • V vedranMv
                                27 Oct 2020, 08:29

                                @JohanSolo Thanks, I for some reason did not think of using delete here at all :D That works just as good!

                                Regarding your edit, what you're writing makes perfect sense, but as you can see in the code, it's the other way around. If I don't call delete manually, I get a segfault. And yes, object gets a parent because I encapsulate it into a container widget, which is then added into the UI window.

                                J Offline
                                J Offline
                                JohanSolo
                                wrote on 27 Oct 2020, 08:32 last edited by
                                #15

                                @vedranMv said in Seg fault when deleting Q3DScatter object:

                                Regarding your edit, what you're writing makes perfect sense, but as you can see in the code, it's the other way around. If I don't call delete manually, I get a segfault.

                                Then it seems to me there must be something else wrong in your code.

                                `They did not know it was impossible, so they did it.'
                                -- Mark Twain

                                1 Reply Last reply
                                0

                                5/15

                                25 Oct 2020, 09:25

                                10 unread
                                • Login

                                • Login or register to search.
                                5 out of 15
                                • First post
                                  5/15
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved