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.
-
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(); } }
-
@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 }
-
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();
} -
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(); }
-
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 }