2012-08-11 121 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