일부 데이터에 맞는 최소 제곱을 실행하는 프로그램이 있습니다. 이 절차는 별도의 스레드에서 실행되며 대화 상자에서 제어됩니다. 이 대화 상자에는 피팅 업데이트와 최종 보고서를 보여주는 QPlainTextEdit가 있습니다.QPlainTextEdit throwing std :: bad_alloc
대화 상자는 Qt 디자이너에서 만들어졌으며, 코드는 QtCreator로 실행되고 Qt 버전은 4.8.1입니다.
내가 겪고있는 문제는 다소 불규칙합니다. 처음 절차를 실행하면 모든 것이 잘됩니다. 내가 다시 실행할 경우, 때때로 프로그램이 메시지
과 충돌이 '표준 : : bad_alloc 뿐이다' 의 인스턴스를 던지는 후 호출 종료 무엇을() : 표준 : : 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 회 실행 한 후 피곤함).
내 유일한 (거의 임의적 인) 추측은 문제가 어떻게 든 스레드에서 업데이트와 관련이 있다는 것입니다 (즉, catch 된 신호를 내고 차례로 UpdateDisplay
함수를 호출 함). 필자가 생각하는 이유는 신호를 주석 처리하고 그냥 가짜 정보로 UpdateDisplay
을 호출하는 새 버튼을 만들면 모든 것이 잘된다는 것입니다.
qApp->processEvents()
위의 공격 라인은 효과가 없습니다.
여기에 붙어 있습니다. 어떤 아이디어라도 환영합니다. 예를 들어, clear()
메서드를 호출하는 것이 ok인지 확인하기 위해 수행 할 수있는 테스트가 있습니까?
스레드에서'QWidget' 메서드를 호출하지 않아야합니다. 스레드로부터 안전하지 않습니다. 메인 GUI 스레드가 볼 수 있도록 신호를 내 보내야하고 메서드를 호출하여 직접 응답해야합니다. – jdi
실로, 당신 말이 맞아요. 나는 그 일에 곤경에 처했습니다. 내 설명이 조금 부족했다. 스레드에서 실행되는 작업자 개체가 있습니다. 업데이트 매개 변수로 신호를 내 보냅니다. 그 신호는 UpdateDisplay를 호출하는 주 앱에 의해 감지됩니다. 나는 이것을 지적하기 위해 질문을 편집했다. – rpsml