I have a program that runs a least squares fit to some data. This procedure is run in a separate thread and controlled from a dialog box. This dialog box has a QPlainTextEdit that shows fitting updates and a final report.
The dialog was created in Qt Designer, the code is run into QtCreator and my Qt version is 4.8.1.
The problem I am running into is somewhat erratic. When I run the procedure a first time, everything is fine. Then if I run it again, sometimes the program crashes with the message
terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc The program has unexpectedly finished.
I tracked the problem to a call to the clear() method of a QPlainTextEdit. Here is some code.
// Snippets of the class definition
class QLSQDialog : public QDialog, public Ui_QLSQDialog
{
Q_OBJECT
public:
QLSQDialog(QWidget *parent = 0);
(...)
void UpdateDisplay(const QString &msg, int iter, double norm); // Update values of chi, etc on displays
signals:
void Run(); // Signal to run a LSQ procedure
(...)
private slots:
void on_btnRun_clicked();
(...)
private:
void Enables(bool running); // Enable and disable features depending on running state of LSQ fit
(...)
};
// Snippets of the class implementation
QLSQDialog::QLSQDialog(QWidget *parent) : QDialog(parent)
{
setupUi(this); // Set up dialog
(...)
txtInfo->clear(); // txtInfo is a QPlainTextEdit created in Designer
(...)
}
void QLSQDialog::UpdateDisplay(const QString &msg, int iter, double norm)
{
lblChi->setText(QString::number(norm,'f',12));
if (iter >= 0) lblIt->setText(QString::number(iter));
txtInfo->appendPlainText(msg);
}
void QLSQDialog::on_btnRun_clicked()
{
txtInfo->clear(); // Offending line in second run
Enables(true);
emit Run();
}
void QLSQDialog::Enables(bool running)
{
bool Idle = !running;
bool HasReport = !txtInfo->document()->isEmpty();
(...)
btnReport->setEnabled(Idle && HasReport);
}
txtInfo
is the QPlainTextEdit object. I call a txtInfo->clear()
when the object is
created to show an empty text edit. When I click on a 'Run' tool button its default slot emits a Run signal that will start the new thread. The txtInfo
QPlainTextEdit is updated in this thread until it finishes (in fact the thread emits a signal that is caught in the main application that in turn calls the UpdateDisplay
).
If I click on the run button a second time, then I get the crash and the error. If I replace txtInfo->clear()
, txtInfo->document()->clear()
, by txtInfo->setPlainText("")
or by txtInfo->document()->setPlainText("")
the problem is the same (crash at second execution). Occasionally, but not frequently, I can run a few times (of the order of 10) before crashing.
Finally, if I comment out the txtInfo->clear()
line, then I can run the routine as much as I tried (in one test I got tired after running it about 80 times).
My only (almost random) guess is that the problem is somehow related to the update from the thread (which emits a signal that is caught and in turn just calls the UpdateDisplay
function). The reason I think so is that if I comment out the signals and just create a new button to call the UpdateDisplay
with some bogus information, everything is fine.
A qApp->processEvents()
before the offending line has no effect.
I am stuck here. Any ideas are welcome. For instance, is there any test I can do to verify that calling the clear()
method is ok?