2012-08-11 80 views
0

我有一个程序运行适合于某些数据的最小二乘方。此过程在单独的线程中运行,并通过对话框进行控制。该对话框有一个QPlainTextEdit,显示适合的更新和最终报告。QPlainTextEdit扔std :: bad_alloc

该对话框是在Qt Designer中创建的,代码运行到QtCreator中,我的Qt版本是4.8.1。

我遇到的问题有些不稳定。当我第一次运行程序时,一切都很好。然后,如果我再次运行它,有时程序与消息

崩溃终止叫做抛出“的std :: bad_alloc的” 的实例以后有什么()的std :: bad_alloc的 该方案已完成意外。

我将问题追踪到调用QPlainTextEdit的clear()方法。这是一些代码。

// 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是QPlainTextEdit对象。当创建对象 以显示空文本编辑时,我会调用txtInfo->clear()。当我点击'运行'工具按钮时,它的默认插槽会发出一个运行信号,以启动新线程。在这个线程中更新了txtInfo QPlainTextEdit,直到完成(实际上线程发出一个信号,该信号在主应用程序中被捕获,然后调用UpdateDisplay)。

如果我第二次点击运行按钮,那么我得到崩溃和错误。如果我替换txtInfo->clear()txtInfo->document()->clear()txtInfo->setPlainText("")txtInfo->document()->setPlainText(""),则问题是相同的(第二次执行时崩溃)。有时候,但不是很频繁,我可以在碰撞之前运行几次(10次左右)。

最后,如果我注释掉txtInfo->clear()这一行,那么我可以像我试过的那样运行例程(在一次测试中,我运行约80次后感到很疲倦)。

我唯一的(几乎是随机的)猜测是这个问题与某个线程的更新有关(它会发出一个被捕获的信号,然后调用UpdateDisplay函数)。我这么认为的原因是,如果我将信号注释掉,并创建一个新的按钮来调用带有一些虚假信息的UpdateDisplay,那么一切都很好。

A qApp->processEvents()在违规行不起作用之前。

我被困在这里。任何想法都欢迎。例如,我可以做任何测试来验证调用clear()方法是否正常?

+1

你可能不应该从线程调用'QWidget'方法。他们不是线程安全的。你需要发出信号给主要的gui线程来查看,并通过调用方法直接回应。 – jdi 2012-08-11 19:10:19

+0

事实上,你是对的,我确实遇到过麻烦。我的描述有点短。我有一个在线程中运行的工作对象。它用更新参数发出一个信号。该信号被主应用程序捕获,该应用程序又调用UpdateDisplay。我编辑了这个问题来指出这一点。 – rpsml 2012-08-11 19:55:58

回答

0

我终于将这个问题追踪到我的代码中令人讨厌的内存泄漏。我“修复了”代码,但对于问题发生的原因,我仍然有点困惑。

基本上,我在某处创建了一个大的vector<double>,并将其地址传递给一个函数,该函数要求一个vector<double> *变量。问题在于原始矢量在函数完成处理之前停止。经典的愚蠢错误。在vector<double>曾经存在的区域中,QPlainTextEdit文档可能会分配空间:期望出现不稳定的行为。但我不希望发生崩溃。

该向量是“只读”的。使用它的函数只读取值并将计算存储在其他地方。现在让我们假设纯文本在vector<double>先前提到的内存中创建了一些内容。在这种情况下,当我使用纯文本文档时,先前由向量指向的值会发生变化,我期望计算是无意义的。当功能访问已故的指针vector<double>时,我也会接受崩溃。但是当我清除文本时,我不希望程序崩溃,毕竟这是一个有效的指针。

无论如何,如果任何人有一个虽然,我会很好奇,知道为什么发生崩溃。但除此之外,一旦泄漏被修复,问题就消失了。当然,知道原因绝对没有理由不修理泄漏。

+0

将您的呼叫附加到该矢量的某个断言上,因此您确定它不会为空。 – linello 2012-08-13 13:12:52

+0

这是很好的建议。但令我感到困惑的是,这次崩溃不是来自访问已故的矢量,而是来自新出生的文本编辑。 – rpsml 2012-08-13 13:33:29

相关问题