SIGSEGV crash with QChart::removeAllSeries().



  • Hi

    I encounter my application crashing with SIGSEGV when trying to use
    QChart::removeAllSeries().
    I have a plot plot_image() function that is called when a "PLOT" button is toggled:

    void MainWindow::plot_image()
    {
        qDebug() << "plot_image() called";
        if(chartWindow->isVisible())
        {
            chartWindow->hide();
            chart->removeAllSeries();
    
        }
        else
        {
            seriesR->clear();
            for(int i=1;i<vecImage.size()+1;i++)
            {
                seriesR->append(i, vecImage.at(i-1).r());
            }
            chart->addSeries(seriesR);
            chartWindow->show();
        }
    }
    

    If I push the button first the chart window opens as desired, if I press again
    it hides, if I press again it crashes.
    Then I removed the " chart->removeAllSeries();" and it does not crash anymore but of cause it complains now that the series is already attached.

    I guess this might be related to this bug but I just want to post it here in the case someone sees a mistake that I made.


  • Lifetime Qt Champion

    Hi,

    Do you have the stack trace of the crash ?



  • I rewrote some simple code:

    mainwindow.cpp:
    
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        chartWindow = new QMainWindow(this);
        chart = new QChart();
        chartView = new QChartView(chart);
        series = new QLineSeries();
        chartWindow->setCentralWidget(chartView);
    }
    
    MainWindow::~MainWindow()
    {
        chart->deleteLater();
        chartView->deleteLater();
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        if(chartWindow->isVisible())
        {
            chartWindow->hide();
            series->clear();
            chart->removeAllSeries();
        }
        else
        {
            series->append(1,9);
            series->append(2,7);
            series->append(3,2);
    
            chart->addSeries(series);
            chartWindow->show();
        }
    }
    

    GDB output (I did not find out yet how to backtrace in qt-creator :/)

    Reading symbols from ./chartCrashTest...done.
    (gdb) r
    Starting program: /mnt/store/c++/qt/build-chartCrashTest-Desktop_Qt_5_7_1-Debug/chartCrashTest 
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib64/libthread_db.so.1".
    [New Thread 0x7fffed660700 (LWP 20981)]
    [New Thread 0x7fffe7fff700 (LWP 20982)]
    
    Thread 1 "chartCrashTest" received signal SIGSEGV, Segmentation fault.
    0x00007ffff7ecf6d9 in ?? () from /usr/lib64/libQt5Charts.so.5
    (gdb) bt
    #0  0x00007ffff7ecf6d9 in ?? () from /usr/lib64/libQt5Charts.so.5
    #1  0x00007ffff7ecf88f in ?? () from /usr/lib64/libQt5Charts.so.5
    #2  0x00007ffff7f46e0a in QtCharts::QXYSeries::append(QPointF const&) () from /usr/lib64/libQt5Charts.so.5
    #3  0x00007ffff7f46e57 in QtCharts::QXYSeries::append(double, double) () from /usr/lib64/libQt5Charts.so.5
    #4  0x000000000040306b in MainWindow::on_pushButton_clicked (this=0x7fffffffd2e0) at ../chartCrashTest/mainwindow.cpp:34
    #5  0x0000000000403f27 in MainWindow::qt_static_metacall (_o=0x7fffffffd2e0, _c=QMetaObject::InvokeMetaMethod, _id=0, 
        _a=0x7fffffffc5c0) at moc_mainwindow.cpp:69
    #6  0x0000000000404020 in MainWindow::qt_metacall (this=0x7fffffffd2e0, _c=QMetaObject::InvokeMetaMethod, _id=0, 
        _a=0x7fffffffc5c0) at moc_mainwindow.cpp:102
    #7  0x00007ffff70cdca9 in QMetaObject::activate(QObject*, int, int, void**) () from /usr/lib64/libQt5Core.so.5
    #8  0x00007ffff79bc232 in QAbstractButton::clicked(bool) () from /usr/lib64/libQt5Widgets.so.5
    #9  0x00007ffff79bc484 in ?? () from /usr/lib64/libQt5Widgets.so.5
    #10 0x00007ffff79be147 in ?? () from /usr/lib64/libQt5Widgets.so.5
    #11 0x00007ffff79be2c4 in QAbstractButton::mouseReleaseEvent(QMouseEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #12 0x00007ffff791c9a8 in QWidget::event(QEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #13 0x00007ffff78d5a6c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #14 0x00007ffff78ddcb5 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #15 0x00007ffff70a778a in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
    #16 0x00007ffff78dc9df in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) () from /usr/lib64/libQt5Widgets.so.5
    #17 0x00007ffff7936be5 in ?? () from /usr/lib64/libQt5Widgets.so.5
    #18 0x00007ffff79395c3 in ?? () from /usr/lib64/libQt5Widgets.so.5
    #19 0x00007ffff78d5a6c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #20 0x00007ffff78dd41e in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/libQt5Widgets.so.5
    #21 0x00007ffff70a778a in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib64/libQt5Core.so.5
    #22 0x00007ffff73d579b in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) ()
       from /usr/lib64/libQt5Gui.so.5
    #23 0x00007ffff73d7635 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*)
        () from /usr/lib64/libQt5Gui.so.5
    #24 0x00007ffff73b859b in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
       from /usr/lib64/libQt5Gui.so.5
    #25 0x00007ffff0701fa0 in ?? () from /usr/lib64/libQt5XcbQpa.so.5
    #26 0x00007ffff4489527 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
    #27 0x00007ffff4489780 in ?? () from /usr/lib64/libglib-2.0.so.0
    #28 0x00007ffff448982c in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0
    #29 0x00007ffff70f4aaf in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
       from /usr/lib64/libQt5Core.so.5
    #30 0x00007ffff70a673a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/libQt5Core.so.5
    #31 0x00007ffff70ae14c in QCoreApplication::exec() () from /usr/lib64/libQt5Core.so.5
    #32 0x0000000000402cd2 in main (argc=1, argv=0x7fffffffd448) at ../chartCrashTest/main.cpp:10
    (gdb)
    


  • @pauledd
    hi,

    the issue seems to be that, that the QLineSeries() object becomes invalid.
    AddSeries takes the ownership of the QLineSeries object. removeAllSeries() deletes the series, and you're left with an invalid pointer.

    simple fix, don't make series a member variable.

    void MainWindow::on_pushButton_clicked()
    {
        if(chartWindow->isVisible())
        {
            chartWindow->hide();
            chart->removeAllSeries();
        }
        else
        {
            QLineSeries *series = new QLineSeries();
    
            series->append(1,9);
            series->append(2,7);
            series->append(3,2);
    
            chart->addSeries(series);
            chartWindow->show();
        }
    }
    


  • I understand, very nice thanks! And because of that I dont need the " series->clear();" anymore because "chart->removeAllSeries();" deletes it completely?



  • @pauledd said in SIGSEGV crash with QChart::removeAllSeries().:

    I understand, very nice thanks! And because of that I dont need the " series->clear();" anymore because "chart->removeAllSeries();" deletes it completely?

    That is correct, removeAllSeries calls delete on each Series object of QChart.

    299 void QChart::removeAllSeries()
    300	{
    301	    foreach (QAbstractSeries *s ,  d_ptr->m_dataset->series()){
    302	        removeSeries(s);
    303	        delete s;
    304	    }
    305	}
    


  • Thanks & marked as solved.



  • A new problem arose:
    now that I have series not as a member I cannot access it anymore from a slot that I also had in that mainwindow. That slot uses mapToValue which needs as second argument the series. Is it possible somehow to access that series from a slot?

    void MainWindow::MousePos2(QRect mp)
    {
    xvalue = chart->mapToValue(mp.topLeft(),series).x();
    }



  • @pauledd
    QChart has a getter function for the series

    QList<QAbstractSeries *> QChart::series() const
    

    so:

    void MainWindow::MousePos2(QRect mp)
    {
    xvalue = chart->mapToValue(mp.topLeft(),chart->series()).x();
    }
    

    should work.



  • Ok, just one more question. What if there was more than one series added to the chart? Should I do this in the order of which the series has been added to the chart?

    void MainWindow::MousePos2(QRect mp)
    {
    xvalue = chart->mapToValue(mp.topLeft(),chart->series().at(0)).x();
    }
    


  • @pauledd

    Add Series appends the series to an internal list, that means as long as you don't swap, or remove individual serieses they are in chronological order:

    77	void ChartDataSet::addSeries(QAbstractSeries *series)
    78	{
    79	    if (m_seriesList.contains(series)) {
    80	        qWarning() << QObject::tr("Can not add series. Series already on the chart.");
    81	        return;
    82	    }
    83	
    84	    // Ignore unsupported series added to polar chart
    85	    if (m_chart && m_chart->chartType() == QChart::ChartTypePolar) {
    86	        if (!(series->type() == QAbstractSeries::SeriesTypeArea
    87	            || series->type() == QAbstractSeries::SeriesTypeLine
    88	            || series->type() == QAbstractSeries::SeriesTypeScatter
    89	            || series->type() == QAbstractSeries::SeriesTypeSpline)) {
    90	            qWarning() << QObject::tr("Can not add series. Series type is not supported by a polar chart.");
    91	            return;
    92	        }
    93	        // Disable OpenGL for series in polar charts
    94	        series->setUseOpenGL(false);
    95	        series->d_ptr->setDomain(new XYPolarDomain());
    96	        // Set the correct domain for upper and lower series too
    97	        if (series->type() == QAbstractSeries::SeriesTypeArea) {
    98	            foreach (QObject *child, series->children()) {
    99	                if (qobject_cast<QAbstractSeries *>(child)) {
    100	                    QAbstractSeries *childSeries = qobject_cast<QAbstractSeries *>(child);
    101	                    childSeries->d_ptr->setDomain(new XYPolarDomain());
    102	                }
    103	            }
    104	        }
    105	    } else {
    106	        series->d_ptr->setDomain(new XYDomain());
    107	    }
    108	
    109	    series->d_ptr->initializeDomain();
    110	    m_seriesList.append(series);
    111	
    112	    series->setParent(this); // take ownership
    113	    series->d_ptr->m_chart = m_chart;
    114	
    115	    emit seriesAdded(series);
    116	}
    

Log in to reply
 

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