Solved QComboBox - unhandled exception if combobox was expanded (drop-down)
-
When ComboBox is clicked user can only choose one of items available on list.
For the moment I use QComboBox only in that way (only when subwindow is created):ui.cbLeftCam->addItems(QStringList()<<"1"<<"2"<<"3"); ui.cbRightCam->addItems(QStringList()<<"a"<<"b"<<"c");
QComboBox object was created using QtDesigner.
Call stack lools like that after crash:
qwindowsd.dll!QScopedPointer<QWindowsContextPrivate,QScopedPointerDeleter<QWindowsContextPrivate> >::operator->() Line 112 + 0x3 bytes C++
qwindowsd.dll!QWindowsContext::windowUnderMouse() Line 648 + 0x8 bytes C++
qwindowsd.dll!QWindowsWindow::destroyWindow() Line 948 + 0x8 bytes C++
qwindowsd.dll!QWindowsWindow::~QWindowsWindow() Line 917 C++
qwindowsd.dll!QWindowsWindow::scalar deleting destructor'() + 0xf bytes C++ Qt5Guid.dll!QWindow::destroy() Line 1597 + 0x23 bytes C++ Qt5Widgetsd.dll!QWidgetPrivate::deleteTLSysExtra() Line 1833 C++ Qt5Widgetsd.dll!QWidget::destroy(bool destroyWindow=true, bool destroySubWindows=true) Line 12200 C++ Qt5Widgetsd.dll!QWidget::~QWidget() Line 1651 C++ Qt5Widgetsd.dll!QFrame::~QFrame() Line 211 + 0x8 bytes C++ Qt5Widgetsd.dll!QComboBoxPrivateContainer::~QComboBoxPrivateContainer() + 0x27 bytes C++ Qt5Widgetsd.dll!QComboBoxPrivateContainer::
scalar deleting destructor'() + 0xf bytes C++
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++
Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++
Qt5Widgetsd.dll!QComboBox::~QComboBox() Line 1325 + 0x8 bytes C++
sMTS.exe!QComboBox::scalar deleting destructor'() + 0x10 bytes C++ Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++ Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++ Qt5Widgetsd.dll!QGroupBox::~QGroupBox() Line 208 + 0x8 bytes C++ sMTS.exe!QGroupBox::
scalar deleting destructor'() + 0x10 bytes C++
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++
Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++
sMTS.exe!QWidget::scalar deleting destructor'() + 0x10 bytes C++ Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++ Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++ sMTS.exe!QWidget::
scalar deleting destructor'() + 0x10 bytes C++
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++
Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++
Qt5Widgetsd.dll!QFrame::~QFrame() Line 211 + 0x8 bytes C++
Qt5Widgetsd.dll!QStackedWidget::~QStackedWidget() Line 143 + 0x8 bytes C++
Qt5Widgetsd.dll!QStackedWidget::vector deleting destructor'() + 0x4d bytes C++ Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++ Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++ Qt5Widgetsd.dll!QTabWidget::~QTabWidget() Line 359 + 0x8 bytes C++ sMTS.exe!QTabWidget::
scalar deleting destructor'() + 0x10 bytes C++
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1950 + 0x24 bytes C++
Qt5Widgetsd.dll!QWidget::~QWidget() Line 1644 C++
sMTS.exe!Calibration::~Calibration() Line 271 + 0xb5 bytes C++
sMTS.exe!Calibration::Instance'::
2'::`dynamic atexit destructor for 'obj''() + 0xd bytes C++
msvcr100d.dll!doexit(int code=0, int quick=0, int retcaller=0) Line 567 C
msvcr100d.dll!exit(int code=0) Line 393 + 0xd bytes C
sMTS.exe!__tmainCRTStartup() Line 568 C
sMTS.exe!WinMainCRTStartup() Line 371 C
kernel32.dll!7634336a()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77e59902()
ntdll.dll!77e598d5()It's odd because it crashes during destroying subwindow "Calibration". It started crash when I created/added QComboBox objects. I did not have this problem earlier (before I add QComboBox object to ui file).
-
Hi,
Which version of Qt are you using ?
On which version of Windows ?
With which compiler ? -
Qt5.4
Win7Pro
Microsoft Visual Studio 2010 -
Are you locked to these outdated version of both Qt and Visual Studio ?
-
To Visual Studio - yes, because other library, I use, have only version for VS2010 (there is no newer version of that library unfortunately).
To Qt - I don't know how much it changed and I would have to change all my code which could cause errors hard to find if I make a simple mistake. So I'd rahter not change if it is unnecessary. -
Fair enough (I know that problem...)
By the way, what graphic card are you using ?
-
@never_ever said in QComboBox - unhandled exception if combobox was expanded (drop-down):
To Visual Studio - yes, because other library, I use, have only version for VS2010 (there is no newer version of that library unfortunately).
To Qt - I don't know how much it changed and I would have to change all my code which could cause errors hard to find if I make a simple mistake. So I'd rahter not change if it is unnecessary.If you need to stick at VS2010, there is not much Qt upgrade possibility (I don't know for Qt 5.5, but 5.6 does not support VS2010 anymore IIRC).
Anyway, I'm still using Qt 4.8, VS2010 and comboboxes. Are you sure the crash is not related to your code?
- What happens if you add the items already in designer?
- Is the subwindow already created when you add the items [i.e. is ui->setupUi() called?]
-
@SGaist NVIDIA GeForce GTX 760
@aha_1980 If I add the items in designer I get the same exception (but this exception shows only if I activate combobox - by pop up list. If I do not use combobox there no exception is shown).
To your second question: yes, subwindow is already created when I add items .
I am not 100% sure that it is not related to my code but I am 95% sure because as I wrote above I have only this two lines of code related to comboxes:ui.cbLeftCam->addItems(QStringList()<<"1"<<"2"<<"3"); ui.cbRightCam->addItems(QStringList()<<"a"<<"b"<<"c");
I do not use any signals from comboboxes.
Before I added them everything was ok (now if I don't activate them it also works fine) -
@never_ever: Can you show your code? Otherwise it's just guessing from our side...
Best would be to boil this down to a minimal working example. On that way, most bugs disappear magically :)
-
It's my code that I simplify (it also crashes). TestComboBox class is main window, and from it I can call subwindow Calibration.
Calibration.h
class Calibration : public QWidget { Q_OBJECT public: static Calibration* Instance(); void changeViewToCalib(); void changeViewToCatch(); void changeToOffline(bool isOffline); signals: void calibrationStarted(bool started); protected: void closeEvent(QCloseEvent* event); private: Calibration(QWidget *parent = 0); ~Calibration(); Calibration(Calibration const&); void operator=(Calibration const&); bool checkCalibrationChoice(); void showEvent(QShowEvent*event); private slots: void closeWindowSlot(); void setSingleCalibrationSlot(bool checked); void setStereoCalibrationSlot(bool checked); void stopCalibSlot(); private: Ui::Calibration ui; QString m_firstCamId; QString m_secondCamId; QCheckBox* m_boxStereo; QCheckBox* m_boxSingle; bool m_offline; bool m_calibImages; bool m_stereoCalibration; bool m_calibStopped; };
Calibration.cpp
Calibration* Calibration::Instance() { static Calibration obj; return &obj; } void Calibration::changeViewToCalib() { setWindowTitle(tr("Calibration")); ui.tabWidget->setTabText(0, tr("Calibration process")); ui.gbProcessType->setTitle(tr("Calibration type")); } void Calibration::changeViewToCatch() { setWindowTitle(tr("Catching images")); ui.tabWidget->setTabText(0, tr("Catching process")); ui.gbProcessType->setTitle(tr("Catching type")); } void Calibration::changeToOffline(bool isOffline) { if(isOffline) { m_offline = true; } else { m_offline = false; } } void Calibration::closeEvent(QCloseEvent* event) { stopCalibSlot(); event->accept(); } Calibration::Calibration(QWidget *parent) : QWidget(parent) { ui.setupUi(this); connect(ui.pbCloseCalibWindow, SIGNAL(clicked()), this, SLOT(closeWindowSlot())); } Calibration::~Calibration() { } bool Calibration::checkCalibrationChoice() { m_firstCamId = m_secondCamId = QString(); if(m_boxStereo->isChecked() && (!m_offline || (m_offline && !m_calibImages))) { int leftIndex = 0; //TEST: ui.cbLeftCam->currentIndex(); int rightIndex = 0; //TEST: ui.cbRightCam->currentIndex(); if(leftIndex == rightIndex) { QMessageBox msg; msg.setText(tr("Error! \nThe same cameras was chosen.")); msg.exec(); return false; } else { m_stereoCalibration = true; m_firstCamId = "";//TEST: ui.cbLeftCam->currentText(); m_secondCamId = "";//TEST: ui.cbRightCam->currentText(); return true; } } else if(m_boxSingle->isChecked()/* && !m_offline*/) { m_stereoCalibration = false; m_firstCamId = ""; //TEST: ui.cbLeftCam->currentText(); return true; } else if(m_offline) { if(m_boxSingle->isChecked()) { m_stereoCalibration = false; return true; } else if(m_boxStereo->isChecked()) { m_stereoCalibration = true; return true; } else return false; } else { QMessageBox msg; msg.setText(tr("Type of calibration not selected")); msg.exec(); return false; } } void Calibration::showEvent(QShowEvent*event) { static bool firstShow = true; // Calibration from loaded images if(m_calibImages) { //QGroupBox* typeCalibBox = new QGroupBox(tr("Choose calibration type"), ui.menuWidget); m_boxSingle = new QCheckBox(tr("Single camera")); m_boxStereo = new QCheckBox(tr("Stereo camera")); } // Calibration from view from cameras or catching images // Create menu to pick calibration type and camera else { if(firstShow) { m_boxSingle = new QCheckBox(tr("Single camera")); m_boxStereo = new QCheckBox(tr("Stereo camera")); QVBoxLayout* vBoxType = new QVBoxLayout(); vBoxType->addWidget(m_boxSingle); vBoxType->addWidget(m_boxStereo); ui.gbProcessType->setLayout(vBoxType); QButtonGroup* typeCalibGroup = new QButtonGroup(ui.gbProcessType); typeCalibGroup->addButton(m_boxSingle); typeCalibGroup->addButton(m_boxStereo); if(!m_calibImages) { connect(m_boxSingle, SIGNAL(toggled(bool)), this, SLOT(setSingleCalibrationSlot(bool))); connect(m_boxStereo, SIGNAL(toggled(bool)), this, SLOT(setStereoCalibrationSlot(bool))); //m_camerasList.clear(); //ui.cbLeftCam->clear(); //ui.cbRightCam->clear(); //ui.cbLeftCam->addItem(tr("Choose left camera...")); //ui.cbRightCam->addItem(tr("Choose right camera...")); ui.cbLeftCam->addItems(QStringList()<<"1"<<"2"<<"3"); ui.cbRightCam->addItems(QStringList()<<"a"<<"b"<<"c"); } m_boxSingle->setChecked(true); ui.cbRightCam->hide(); typeCalibGroup->setExclusive(true); } } QWidget::showEvent(event); m_calibStopped = true; } void Calibration::closeWindowSlot() { stopCalibSlot(); close(); } void Calibration::setSingleCalibrationSlot(bool checked) { ui.cbRightCam->hide(); } void Calibration::setStereoCalibrationSlot(bool checked) { ui.cbRightCam->show(); } void Calibration::stopCalibSlot() { if(m_calibStopped) { emit calibrationStarted(false); return; } m_calibStopped = true; }
TestComboBox.h
class testComboBox : public QMainWindow { Q_OBJECT public: testComboBox(QWidget *parent = 0); ~testComboBox(); public slots: void catchImages(); void setCameraCaptureState(bool isCaptured); private: Ui::testComboBoxClass ui; bool m_calibrationStarted; };
TestComboBox.cpp
testComboBox::testComboBox(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); connect(ui.actionImages, SIGNAL(triggered()), this, SLOT(catchImages())); connect(Calibration::Instance(), SIGNAL(calibrationStarted(bool)), this, SLOT(setCameraCaptureState(bool)), Qt::UniqueConnection); } testComboBox::~testComboBox(){} void testComboBox::catchImages() { if(m_calibrationStarted) { QMessageBox::warning(this, tr("Warning"), tr("Capture in progress! \nIf you want make changes stop process."), QMessageBox::Ok); return; } Calibration::Instance()->changeViewToCatch(); Calibration::Instance()->changeToOffline(true); Calibration::Instance()->show(); } void testComboBox::setCameraCaptureState(bool isCaptured) { m_calibrationStarted = isCaptured; }
-
The problem is with the static instance of
Calibration
. Many of Qt's internal mechanisms rely on the existance of application object. Since static variables are destroyed aftermain()
exits the application instance is no longer there.
Instances ofQObject
derived classes should never outlive the application object.If you need a
QObject
derived singleton use a static pointer and release it before you exit application object's scope, e.g.Calibration* Calibration::Instance() { static Calibration* obj = nullptr; if (!obj) { obj = new Calibration(); conntect(qApp, &QCoreApplication::aboutToQuit, obj, &Calibration::deleteLater); } return obj; }
-
Thanks, it really helps.
-
@never_ever I met the same problem and use
exit()
instead ofreturn a.exec()
, program can exit normally -
@trreeee
And as I wrote you in your topic for that it is a bad idea to useexit()
rather than fixing your destructor code, so should not be recommended to other people. And I see @Chris-Kawa above recommends the same as I did there:If you need a QObject derived singleton use a static pointer and release it before you exit application object's scope