Program.exe has stopped working
-
Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.
-
@cpper
Consider this:char * test = new char[4]; test[0] = 'A'; test[3] = 'C'; delete test; //< Now we don't have the memory anymore qDebug() << test[3]; //< Reading an invalid location, yet you'd probably get 'C' and no crash
It's the same with objects, until memory is overwritten you have a good chance that your object is still there, so getting a value for:
qDebug() << series->at(0).x();
just means nothing.
What does this print out:
void MainWindow::on_pushButton_clicked() { // ... Your code before loop.exec() goes here ... QPointer<QLineSeries> guarded(series); loop.exec(); if (!guarded) qDebug() << "Ouch! We have a nasty ownership problem, we want to delete an object we don't own ..."; else { qDebug() << "We are okay, series points to a valid object"; delete series; } }
-
It prints ""We are okay, series points to a valid object".
If guarded pointer points to the QChart it prints ""Ouch! We have a nasty ownership problem, we want to delete an object we don't own ...";
So this finally confirms that the chart gets deleted but the series not, right ?@SGaist said in Program.exe has stopped working:
Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.
After loop.exec() try qDebug()<<series , and qDebug()<<chart . The first one works but the second crashed the program.
Or consider this: QWidget* w=new QWidget(); qDebug()<<w; . This works and prints an address. But QWidget* w=new QWidget(); delete w; qDebug()<<w; crashes the program.
I'm not saying that you are wrong, but trying to qDebug() a deleted pointer crashes the program. Since qDebug()<<series worked for me means series wasn't deleted. Or ? -
@cpper said in Program.exe has stopped working:
So this finally confirms that the chart gets deleted but the series not, right ?
No, not necessarily. It means that
series
is not deleted directly (withdelete
), it can however be scheduled for deletion (withQObject::deleteLater
). And one of the specific things about local event loops is that they don't process those events, they delegate them to the higher-level event loop. So, you may still be getting a double deletion. The other thing that you could try and it will ultimately show whether or not the object is deleted by thechart
is if you attach to theQObject::destroyed
signal (instead of deleting it explicitly):void MainWindow::on_pushButton_clicked() { // ... loop.exec(); // delete series; QObject::connect(series, &QObject::destroyed, [] (QObject *) -> void { qDebug() << "Series is deleted in the parent event loop!" }); }
Of course, you can also just try substituting
delete series
withseries->deleteLater()
, which would solve your problem, if it is in fact a double deletion. -
The slot is indeed called. So the conclusion of the illusion is that the chart is immediately destroyed after the widget is closed, but the series is later destroyed. This explains everything. Thanks guys for being pacient and making everything clear to me.
-
This was the original code:
QEventLoop loop; chartView->setAttribute( Qt::WA_DeleteOnClose ); connect(chartView,&QChartView::destroyed,&loop,&QEventLoop::quit); chartView->show(); loop.exec(); delete series;
Now that I've learned that deleting the chartView also deletes the chart,series, and axis, I've replaced the code with :
chartView->setAttribute( Qt::WA_DeleteOnClose ); chartView->show();
And it works like a charm now. Of course, the complete version of the program.
One last thing I've noticed: If I explicitly delete series, the program does not crash if it automatically wants to delete series (later). But if the program has already automatically deleted series and I try to explicitly delete it afterwards, I get the "program.exe has stopped working". That being said, it seems the automatic deletion(the ownership thing) checks firstly if the pointer is still valid, like you did in the example with the "guarded" pointer.
-
@cpper said in Program.exe has stopped working:
That being said, it seems the automatic deletion(the ownership thing) checks firstly if the pointer is still valid, like you did in the example with the "guarded" pointer.
It does, sort of - it removes the pending events for the object, because Qt has to guarantee that multiple calls to QObject::deleteLater don't lead to side effects (as is documented) .