Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. SIGSEV on ~QColorSpace Destructor
Forum Updated to NodeBB v4.3 + New Features

SIGSEV on ~QColorSpace Destructor

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 3 Posters 448 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    GrafZ4hl
    wrote on last edited by GrafZ4hl
    #1

    Hello!

    I'm currently in the process of implementing an opencv based object tracker and I want to show the cv::Mats on some forms using QT. So far I've implemented a QTimer to poll a buffer which gets filled by a pipeline, running in another thread. On every timer tick I convert the cv::Mats to QPixmaps using QImage (see Code #1 below). Now after roughly 1 minute and 15-20 seconds the whole programm crashes at ~QColorSace (line 479). Even if I don't convert the images and just let the program run it'll crash at the same exact spot, giving me following stack:

    1  QColorSpace::~QColorSpace    qcolorspace.cpp           479  0x7fffe40e9ebc 
    2  QImageData::~QImageData      qimage.cpp                169  0x7fffe3f565de 
    3  QImage::~QImage              qimage.cpp                1027 0x7fffe3f56ab7 
    4  QRasterPlatformPixmap::~QRasterPlatformPixmap     
    qpixmap_raster.cpp        88   0x7fffe3f9085c 
    
    5  QRasterPlatformPixmap::~QRasterPlatformPixmap     
    qpixmap_raster.cpp        90   0x7fffe3f90879 
    
    6  QExplicitlySharedDataPointer<QPlatformPixmap>::~QExplicitlySharedDataPointer qshareddata.h  184 0x7fffe3f86411 
    
    7  QPixmap::~QPixmap     qpixmap.cpp               263  0x7fffe3f86411 
    8  QPixmapCacheEntry::~QPixmapCacheEntry  qpixmapcache.cpp          480  0x7fffe3f8ae1f 
    9  QPixmapCacheEntry::~QPixmapCacheEntry qpixmapcache.cpp          483  0x7fffe3f8ae1f 
    10 QCache<QPixmapCache::Key, QPixmapCacheEntry>::unlink qcache.h                  69   0x7fffe3f8ae1f 
    11 QCache<QPixmapCache::Key, QPixmapCacheEntry>::trim     qcache.h                  193  0x7fffe3f8ae1f 
    12 QCache<QPixmapCache::Key, QPixmapCacheEntry>::setMaxCost  qcache.h                  129  0x7fffe3f8ae1f 
    13 QPMCache::flushDetachedPixmaps           qpixmapcache.cpp          290  0x7fffe3f8ae1f 
    14 QPMCache::timerEvent                     qpixmapcache.cpp          312  0x7fffe3f8b4e5 
    15 QObject::event                           qobject.cpp               1336 0x7fffe31f6cab 
    16 QApplicationPrivate::notify_helper       qapplication.cpp          3671 0x7fffe483413c 
    17 QApplication::notify                     qapplication.cpp          3417 0x7fffe483ad10 
    18 QCoreApplication::notifyInternal2        qcoreapplication.cpp      1061 0x7fffe31c78f8 
    19 QCoreApplication::sendEvent              qcoreapplication.cpp      1456 0x7fffe31c7aae 
    20 QTimerInfoList::activateTimers           qtimerinfo_unix.cpp       643  0x7fffe32225d9 
    21 timerSourceDispatch                      qeventdispatcher_glib.cpp 183  0x7fffe3222db1 
    22 g_main_context_dispatch                  0x7fffe52db417 
    23 ??                                       0x7fffe52db650 
    24 g_main_context_iteration                 0x7fffe52db6dc 
    25 QEventDispatcherGlib::processEvents      qeventdispatcher_glib.cpp 423  0x7fffe322311c 
    26 QEventLoop::exec                         qeventloop.cpp            232  0x7fffe31c630a 
    27 QCoreApplication::exec                   qcoreapplication.cpp      1369 0x7fffe31cf2b3 
    28 main                                     App_main.cpp              26   0x555555579b99 
    
    

    With d_ptr:

    this	@0x7fffb400ab18	QColorSpace
      d_ptr	    0xb3baf80208b	  QColorSpacePrivate*
      staticMetaObject	@0x7fffe46b4020	QMetaObject
    
    

    I've tried to implement a new PixmapCache for said image but that didn't work either.
    Code#1:

    void  frm_Main::C_frm_Main::FillMat2Lbl(cv::Mat& img, QLabel& label)
      {
      cv::Mat* imgPtr = &img;
      if(imgPtr == nullptr)
        return;
      else if(img.empty())
        return;
      else if(this->PixmapCache->find(*this->PixmapKey, this->QPixImg))
        {
        *this->Qimg = this->cvMatToQImage(img);
        this->QPixImg->convertFromImage(*this->Qimg);
        label.setPixmap(QPixImg->scaled(label.size(), Qt::KeepAspectRatio));
        }
      else
          return;
    
    inline QImage   frm_Main::C_frm_Main::cvMatToQImage( const cv::Mat &inMat )
       {
       switch ( inMat.type() )
         {
         // 8-bit, 4 channel
         case CV_8UC4:
           {
           QImage image( inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_RGB32 );
           QImage copy(image);
           copy.bits(); //enforce deep copy
           return copy;
           }
         // 8-bit, 3 channel
         case CV_8UC3:
           {
           QImage image( (uchar*)inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_RGB888 );
           return image.rgbSwapped().copy();
           }
         // 8-bit, 1 channel
         case CV_8UC1:
           {
           static QVector<QRgb>  sColorTable;
           // only create our color table once
          if ( sColorTable.isEmpty() )
            {
            for ( int i = 0; i < 256; ++i )
                  sColorTable.push_back( qRgb( i, i, i ) );
            }
            QImage image( inMat.data, inMat.cols, inMat.rows, inMat.step, QImage::Format_Indexed8 );
            image.setColorTable( sColorTable );
            QImage copy(image);
            copy.bits(); //enforce deep copy
            return copy;
           }
         default:
           qWarning() << "***ERROR*** ::cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();
           break;
          }
          return QImage();
       }
    

    I feel like that error has nothing to do with the FillMat2Lbl but rather with some wonky implementation of the QTimer on my end, but as it stands I'm completely clueless on what to do.
    Also I'm fairly new to C++ and an absolute beginner in QT, so every hint is greatly appreciated!

    Best

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      When you say you poll a thread? Where does FillMat2Lbl() get it's data from? Are you sure you're in the main thread here?
      Why do you need an own pixmap cache what do you think you gain with it?
      Why do you use QImage and QPixmap as pointer even you never need it at all?
      This can never be true since you can't pass a null reference.

        cv::Mat* imgPtr = &img;
        if(imgPtr == nullptr)
          return;
      

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • G Offline
        G Offline
        GrafZ4hl
        wrote on last edited by GrafZ4hl
        #3

        @Christian-Ehrlicher First of, thanks for you response!
        **When you say you poll a thread? Where does FillMat2Lbl() get it's data from? **
        I have a tbb pipeline running in the background which grabs new images from webcams, does some work on it(filter, calculations, etc) and the pushes the whole data package as a payload into tbb Que. The timer tries to pop a payload from said Que and hands it over to FillMat2Lbl():

        void C_frm_Object_Calibration::Taktgeber_Tick()
          {
          this->Ui->txb_zaehler->setText(QString::number(this->Zaehler++));
            if(this->Main->cameraManager->pipelineQue->try_pop(pData))
              {
              this->Main->frm_Main->FillMat2Lbl(pData->cpuSrcImg[0], *this->Ui->lbl_src_img);
              this->Main->frm_Main->FillMat2Lbl(pData->cpuGrayImg[0], *this->Ui->lbl_img_gray);
              this->Main->frm_Main->FillMat2Lbl(pData->cpuUndistortedImg[0], *this->Ui->lbl_imgFinal);
              this->Ui->txb_fps->setText(QString::number(pData->fps));
              this->Ui->txb_frametime->setText(QString::number(pData->frametime.count()));
              this->Ui->txb_worker_1->setText(QString::number(pData->executionTime[0].count()));
              this->Ui->txb_worker_2->setText(QString::number(pData->executionTime[1].count()));
              this->Ui->txb_worker_3->setText(QString::number(pData->executionTime[2].count()));
              this->Ui->txb_worker_4->setText(QString::number(pData->executionTime[3].count()));
              this->Ui->txb_worker_5->setText(QString::number(pData->executionTime[4].count()));
              this->Ui->txb_worker_6->setText(QString::number(pData->executionTime[5].count()));
              this->Ui->txb_worker_7->setText(QString::number(pData->executionTime[6].count()));
              this->Ui->txb_worker_8->setText(QString::number(pData->executionTime[7].count()));
            delete(pData);
            }
          }
        
        

        ** Are you sure you're in the main thread here?**
        I'm pretty sure, yes. In theory there is just the main thread + tbb pipeline threads. Is there a way to check if its running in main thread?
        Why do you need an own pixmap cache what do you think you gain with it?
        Well I thought the crash has something to do with the default cache being to small so I've tried to implement a bigger one but that didn't do anything unfortunately.
        Why do you use QImage and QPixmap as pointer even you never need it at all?
        I'm don't really get whats wrong with using pointers, could you elaborate please? I've defined those Pointers in my .h and declared them with new. That might be a bad design choice but unfortunately that is how my Professor wants me to do it.
        This can never be true since you can't pass a null reference.
        Thanks for pointing out! Gonna delete that part

        EDIT
        According to that small code snipped the timer runs in main thread:

        Main.cpp
          this->MAIN_THREAD_ID = std::this_thread::get_id();
        
        frm_camera_calibration.cpp
        void C_frm_Camera_Calibration::Taktgeber_Tick()
        {
           if (std::this_thread::get_id() == this->Main->MAIN_THREAD_ID)
             {
             std::cout << "C_frm_Object_Calibration::Taktgeber_Tick main thread\n";
             }
           else
             {
             std::cout << "C_frm_Object_Calibration::Taktgeber_Tick not main thread\n";
             }
        }
          
        
        Christian EhrlicherC 1 Reply Last reply
        0
        • G GrafZ4hl

          @Christian-Ehrlicher First of, thanks for you response!
          **When you say you poll a thread? Where does FillMat2Lbl() get it's data from? **
          I have a tbb pipeline running in the background which grabs new images from webcams, does some work on it(filter, calculations, etc) and the pushes the whole data package as a payload into tbb Que. The timer tries to pop a payload from said Que and hands it over to FillMat2Lbl():

          void C_frm_Object_Calibration::Taktgeber_Tick()
            {
            this->Ui->txb_zaehler->setText(QString::number(this->Zaehler++));
              if(this->Main->cameraManager->pipelineQue->try_pop(pData))
                {
                this->Main->frm_Main->FillMat2Lbl(pData->cpuSrcImg[0], *this->Ui->lbl_src_img);
                this->Main->frm_Main->FillMat2Lbl(pData->cpuGrayImg[0], *this->Ui->lbl_img_gray);
                this->Main->frm_Main->FillMat2Lbl(pData->cpuUndistortedImg[0], *this->Ui->lbl_imgFinal);
                this->Ui->txb_fps->setText(QString::number(pData->fps));
                this->Ui->txb_frametime->setText(QString::number(pData->frametime.count()));
                this->Ui->txb_worker_1->setText(QString::number(pData->executionTime[0].count()));
                this->Ui->txb_worker_2->setText(QString::number(pData->executionTime[1].count()));
                this->Ui->txb_worker_3->setText(QString::number(pData->executionTime[2].count()));
                this->Ui->txb_worker_4->setText(QString::number(pData->executionTime[3].count()));
                this->Ui->txb_worker_5->setText(QString::number(pData->executionTime[4].count()));
                this->Ui->txb_worker_6->setText(QString::number(pData->executionTime[5].count()));
                this->Ui->txb_worker_7->setText(QString::number(pData->executionTime[6].count()));
                this->Ui->txb_worker_8->setText(QString::number(pData->executionTime[7].count()));
              delete(pData);
              }
            }
          
          

          ** Are you sure you're in the main thread here?**
          I'm pretty sure, yes. In theory there is just the main thread + tbb pipeline threads. Is there a way to check if its running in main thread?
          Why do you need an own pixmap cache what do you think you gain with it?
          Well I thought the crash has something to do with the default cache being to small so I've tried to implement a bigger one but that didn't do anything unfortunately.
          Why do you use QImage and QPixmap as pointer even you never need it at all?
          I'm don't really get whats wrong with using pointers, could you elaborate please? I've defined those Pointers in my .h and declared them with new. That might be a bad design choice but unfortunately that is how my Professor wants me to do it.
          This can never be true since you can't pass a null reference.
          Thanks for pointing out! Gonna delete that part

          EDIT
          According to that small code snipped the timer runs in main thread:

          Main.cpp
            this->MAIN_THREAD_ID = std::this_thread::get_id();
          
          frm_camera_calibration.cpp
          void C_frm_Camera_Calibration::Taktgeber_Tick()
          {
             if (std::this_thread::get_id() == this->Main->MAIN_THREAD_ID)
               {
               std::cout << "C_frm_Object_Calibration::Taktgeber_Tick main thread\n";
               }
             else
               {
               std::cout << "C_frm_Object_Calibration::Taktgeber_Tick not main thread\n";
               }
          }
            
          
          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @GrafZ4hl said in SIGSEV on ~QColorSpace Destructor:

          That might be a bad design choice but unfortunately that is how my Professor wants me to do it.

          But that's not the Qt way of handling QImage and QPixmap. Esp. since you don't need either of them:

          auto image = cvMatToQImage(img);
          auto pixmap = QPixmap::fromImage(image);
          label.setPixmap(pixmap.scaled(label.size(), Qt::KeepAspectRatio));
          

          On the other hand you pass references where Qt gives you pointer (e.g. the QLabels) - this somehow looks very inconsistent.
          And no, "this->" is no c++ way either - it's java-style and is just for people who are paid by characters :)

          This avoid some (de)allocations.

          Now to your problem - you said it also crashes when you don't convert anything. So you mean you don't call cvMatToQImage()?

          Are you sure cameraManager->pipelineQue() doesn't overflow?

          If you're on linux I would say use AdressSanitizer or valgrind to see what goes wrong.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          G 1 Reply Last reply
          1
          • Christian EhrlicherC Christian Ehrlicher

            @GrafZ4hl said in SIGSEV on ~QColorSpace Destructor:

            That might be a bad design choice but unfortunately that is how my Professor wants me to do it.

            But that's not the Qt way of handling QImage and QPixmap. Esp. since you don't need either of them:

            auto image = cvMatToQImage(img);
            auto pixmap = QPixmap::fromImage(image);
            label.setPixmap(pixmap.scaled(label.size(), Qt::KeepAspectRatio));
            

            On the other hand you pass references where Qt gives you pointer (e.g. the QLabels) - this somehow looks very inconsistent.
            And no, "this->" is no c++ way either - it's java-style and is just for people who are paid by characters :)

            This avoid some (de)allocations.

            Now to your problem - you said it also crashes when you don't convert anything. So you mean you don't call cvMatToQImage()?

            Are you sure cameraManager->pipelineQue() doesn't overflow?

            If you're on linux I would say use AdressSanitizer or valgrind to see what goes wrong.

            G Offline
            G Offline
            GrafZ4hl
            wrote on last edited by
            #5

            @Christian-Ehrlicher
            But that's not the Qt way of handling QImage and QPixmap. Esp. since you don't need either of them:
            That sounds like a fair point! My usecase is highly time critical, that why I thought I could avoid some unnecessary overhead by using pointer instead of allocating new QImages/QPixmaps on every function call.

            And no, "this->" is no c++ way either - it's java-style and is just for people who are paid by characters :)
            Oh well I'm not gonna tell him! That'd surely be noticable in my final grade

            Are you sure cameraManager->pipelineQue() doesn't overflow?
            Intel tbb has some build in thread safe overflow protections to keep the Que in a fixed size so I recon it won't be that function.

            you said it also crashes when you don't convert anything. So you mean you don't call cvMatToQImage()?
            Exactly! I've commented every line on my timer_tick function but it still crashes after 1-1,5 minutes. So I think theres nothing wrong with my image conversion but rather with the timer. As before I've declared a pointer in frm_camera_calibration.h

            frm_camera_calibration.h
            
              QTimer*  Taktgeber;
            
            

            Constructed the timer in frm_camera_calibration.cpp

            C_frm_Camera_Calibration::C_frm_Camera_Calibration(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) :
                QMainWindow(parent)
            {
                this->Taktgeber  = new QTimer(this);
            }
            
            

            And started the timer in showEvent()

            void C_frm_Camera_Calibration::showEvent(QShowEvent* ShowEvent)
            {
            Q_UNUSED(ShowEvent)    
            this->Zaehler                     = 0;
            this->Taktgeber_Intervall         = 25;
            connect                           (this->Taktgeber, &QTimer::timeout, this, &C_frm_Camera_Calibration::Taktgeber_Tick);
            this->Taktgeber->start            (this->Taktgeber_Intervall);
            this->installEventFilter          (this);
            }
            
            

            Again abundant usage of "this->".. Its a thing I have to get used to first.

            If you're on linux I would say use AdressSanitizer or valgrind to see what goes wrong.
            I'll give Valgrind a go. Do you, by any chance, have some good guides at hand on how to use it?

            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              I would not set up the timer in the showEvent() since this can be called more than once.
              And does it crash when the timer does not run?

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              G 1 Reply Last reply
              2
              • Christian EhrlicherC Christian Ehrlicher

                I would not set up the timer in the showEvent() since this can be called more than once.
                And does it crash when the timer does not run?

                G Offline
                G Offline
                GrafZ4hl
                wrote on last edited by
                #7

                @Christian-Ehrlicher
                I would not set up the timer in the showEvent() since this can be called more than once.
                So a better way to set it up would be using an external call on frm->show?

                And does it crash when the timer does not run?
                Yeah unfortunately its the same behaviour even if I comment it out

                //connect (this->Taktgeber, &QTimer::timeout, this, &C_frm_Camera_Calibration::Taktgeber_Tick);
                //this->Taktgeber->start            (this->Taktgeber_Intervall);
                //this->installEventFilter          (this);
                
                

                So in my program frm_main is like a main menu which calls frm_camera_positioning, frm_camera_calibration and so on but every new form has its own QTimer and EventFilter. Is that the right way to do it? Also, every window is declared as

                C_frm_Camera_Calibration : public QMainWindow
                C_frm_Camera_Positioning : public QMainWindow
                C_frm_Main : public QMainWindow
                
                C_frm_Camera_Calibration::C_frm_Camera_Calibration(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : QMainWindow(parent)
                
                C_frm_Camera_Positioning::C_frm_Camera_Positioning(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : QMainWindow(parent)
                
                C_frm_Main::C_frm_Main(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : (QMainWindow(parent)
                

                Well another try with commented QTimer and installEventFilter on every form failed with the same issue...

                kshegunovK 1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  The setup should be done in the ctor or separate init() function.

                  For the crash - reduce your program until it no longer crashes :)

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  3
                  • G GrafZ4hl

                    @Christian-Ehrlicher
                    I would not set up the timer in the showEvent() since this can be called more than once.
                    So a better way to set it up would be using an external call on frm->show?

                    And does it crash when the timer does not run?
                    Yeah unfortunately its the same behaviour even if I comment it out

                    //connect (this->Taktgeber, &QTimer::timeout, this, &C_frm_Camera_Calibration::Taktgeber_Tick);
                    //this->Taktgeber->start            (this->Taktgeber_Intervall);
                    //this->installEventFilter          (this);
                    
                    

                    So in my program frm_main is like a main menu which calls frm_camera_positioning, frm_camera_calibration and so on but every new form has its own QTimer and EventFilter. Is that the right way to do it? Also, every window is declared as

                    C_frm_Camera_Calibration : public QMainWindow
                    C_frm_Camera_Positioning : public QMainWindow
                    C_frm_Main : public QMainWindow
                    
                    C_frm_Camera_Calibration::C_frm_Camera_Calibration(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : QMainWindow(parent)
                    
                    C_frm_Camera_Positioning::C_frm_Camera_Positioning(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : QMainWindow(parent)
                    
                    C_frm_Main::C_frm_Main(C_GlobalObjects* GlobalObjects, C_Main* Main, QWidget *parent) : (QMainWindow(parent)
                    

                    Well another try with commented QTimer and installEventFilter on every form failed with the same issue...

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

                    @GrafZ4hl said in SIGSEV on ~QColorSpace Destructor:

                    connect (this->Taktgeber, &QTimer::timeout, this, &C_frm_Camera_Calibration::Taktgeber_Tick);

                    What is this?

                    if(this->Main->cameraManager->pipelineQue->try_pop(pData))

                    What is pData?
                    What is pipelineQue?
                    What's the implementation of try_pop?

                    I'd hazard that your pData's containing garbage or doesn't live long enough for whatever it is you're trying to do.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved