QComboBox - unhandled exception if combobox was expanded (drop-down)



  • Hi,
    I have problem with QComboBox (I think that it is the problem but maybe sth else). I created main window where I can call other subwindows. In one of them I added 2 objects of QComboBox (created in QtDesigner). I add items to the combos in one place of my code. During exiting program (when main window is exiting and all child windows are being destroyed) I get unhandled exception if earlier I clicked on one of the comboboxes and it was extended. If comboboxes weren't clicked or activated everything exiting well without exception.

    Unhandled exception at 0x5825fbbc (qwindowsd.dll) in sMTSystem.exe: 0xC0000005: Access violation reading location 0x00000000.
    

    Something is called that probably was destroyed earlier but first time I can't catch where. But it only crashes when combobox was used (when list was expanded). In comboboxes I have only strings.


  • Qt Champions 2017

    Hi
    Thats a bid odd. (since the items lives in combobox)
    When combo is clicked, what do you do in slot ?

    If you crash it in debugger, dont the call stack shows what happens ?



  • 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).


  • Lifetime Qt Champion

    Hi,

    Which version of Qt are you using ?
    On which version of Windows ?
    With which compiler ?



  • Qt5.4
    Win7Pro
    Microsoft Visual Studio 2010


  • Lifetime Qt Champion

    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.


  • Lifetime Qt Champion

    Fair enough (I know that problem...)

    By the way, what graphic card are you using ?


  • Qt Champions 2017

    @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)


  • Qt Champions 2017

    @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;
    }

  • Moderators

    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 after main() exits the application instance is no longer there.
    Instances of QObject 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.