1

一部のデータに対して最小二乗法を実行するプログラムがあります。このプロシージャは別のスレッドで実行され、ダイアログ ボックスから制御されます。このダイアログ ボックスには、フィッティングの更新と最終レポートを表示する QPlainTextEdit があります。

ダイアログは Qt Designer で作成され、コードは QtCreator で実行され、私の Qt バージョンは 4.8.1 です。

私が直面している問題は、やや不安定です。手順を初めて実行するときは、すべて問題ありません。その後、もう一度実行すると、プログラムがクラッシュしてメッセージが表示されることがあります

'std::bad_alloc' what() のインスタンスをスローした後に呼び出された終了: 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);
}

txtInfoQPlainTextEdit オブジェクトです。オブジェクトが作成されたときに を呼び出してtxtInfo->clear()、空のテキスト編集を表示します。「実行」ツール ボタンをクリックすると、そのデフォルト スロットが新しいスレッドを開始する実行シグナルを発します。QPlainTextEdit は、txtInfo終了するまでこのスレッドで更新されます (実際、スレッドは、メイン アプリケーションでキャッチされるシグナルを発し、次に を呼び出しますUpdateDisplay)。

もう一度実行ボタンをクリックすると、クラッシュとエラーが発生します。txtInfo->clear()txtInfo->document()->clear()、 、txtInfo->setPlainText("")または byを置き換えるとtxtInfo->document()->setPlainText("")、問題は同じです (2 回目の実行でクラッシュします)。頻繁ではありませんが、時折、クラッシュする前に数回 (10 回程度) 実行できます。

最後に、行をコメント アウトすると、txtInfo->clear()実行した回数だけルーチンを実行できます (あるテストでは、約 80 回実行した後に疲れました)。

私の唯一の(ほぼランダムな)推測は、問題がスレッドからの更新に何らかの形で関連していることです(キャッチされたシグナルを発し、UpdateDisplay関数を呼び出すだけです)。私がそう思う理由は、シグナルをコメントアウトして、UpdateDisplay偽の情報で呼び出すための新しいボタンを作成すれば、すべて問題ないからです。

問題のある行の前のAqApp->processEvents()は効果がありません。

私はここで立ち往生しています。どんなアイデアでも大歓迎です。たとえば、clear()メソッドの呼び出しに問題がないことを確認するために実行できるテストはありますか?

4

1 に答える 1

0

私はついにこの問題をコードの厄介なメモリリークまで追跡しました。コードを「修復」しましたが、問題が発生した理由にまだ少し戸惑っています。

基本的に、私はどこかにラージを作成し、そのアドレスを変数vector<double>を呼び出す関数に渡していました。vector<double> *問題は、関数が動作を終了する前に元のベクトルがなくなったことでした。古典的なばかげた間違い。おそらく、QPlainTextEditドキュメントは以前の領域にスペースを割り当てていましたvector<double>:不安定な動作が予想されました。しかし、私はクラッシュを期待していません。

ベクトルは「読み取り専用」でした。それを使用する関数は、値を読み取り、別の場所に保存された計算を行うだけです。ここで、プレーンテキストが以前に。によってアドレス指定されたメモリに何かを作成すると仮定しましょうvector<double>。この場合、私QPlainTextEdit::clear()がプレーンテキストのドキュメントである場合、以前にベクトルによって示された値が変化し、計算が無意味であると予想します。また、関数が現在は廃止されたへのポインタにアクセスすると、クラッシュを受け入れますvector<double>。しかし、テキストをクリアしたときにプログラムがクラッシュすることはないと思います。これは結局のところ有効なポインタです。

とにかく、誰かが持っているなら、私はクラッシュが起こる理由を知りたいと思います。ただし、それ以外の場合は、リークが修復されると問題は解消されます。そしてもちろん、理由を知ることは、漏れを修理しない言い訳にはなりません。

于 2012-08-13T12:45:32.240 に答える