Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-65077

Bug in QQuickPixmapStore::~QQuickPixmapStore.

    XMLWordPrintable

Details

    • c57681bc376d1d912d23b044c48932fa8f7816d7 (qt/qtdeclarative/5.12)

    Description

      I have the following callstack

                    Qt5QuickRTILd.dll!QHash<QQuickPixmapKey,QQuickPixmapData * __ptr64>::remove(const QQuickPixmapKey & akey) Line 790   C+                Qt5QuickRTILd.dll!QQuickPixmapData::removeFromCache() Line 1164 C                Qt5QuickRTILd.dll!QQuickPixmapData::release() Line 1143         C                Qt5QuickRTILd.dll!QQuickPixmapStore::~QQuickPixmapStore() Line 949             C+ 

      Code is: 

          // unreference all (leaked) pixmaps
          for (auto *pixmap : qAsConst(m_cache)) {
              int currRefCount = pixmap->refCount;
              if (currRefCount) {
      #ifndef QT_NO_DEBUG
                  leakedPixmaps++;
      #endif
                  while (currRefCount > 0) {
                      pixmap->release();    // this is Qt5QuickRTILd.dll!QQuickPixmapStore::~QQuickPixmapStore() Line 949    C++
                      currRefCount--;
                  }
              }
          }
      

      I think it is not allowed to remove the element of a QHash, where your iterator points to. This only happens if there is a  pixmapdata with pixmapStatus != QQuickPixmap::Ready.

      In fact I get a crash afterwards.

      Qt5CoreRTILd.dll!QHashData::nextNode(QHashData::Node * node) Line 614     C+                Qt5QuickRTILd.dll!QHash<QQuickPixmapKey,QQuickPixmapData * __ptr64>::const_iterator::operator() Line 394                C                Qt5QuickRTILd.dll!QQuickPixmapStore::~QQuickPixmapStore() Line 941             C+Exception thrown: read access violation.

      d was 0xFFFFFFFFFFFFFFFF.

      This happens in a unittest, where a async Quickimage is instantiated and shut down in a sequence.

      IMHO this would fix the problem:

          // unreference all (leaked) pixmaps
          for (auto *pixmap : qAsConst(m_cache)) {
              int currRefCount = pixmap->refCount;
              if (currRefCount) {
      #ifndef QT_NO_DEBUG
                  leakedPixmaps++;
      #endif
                  pixmap->inCache = false;  // FIX                  
                  while (currRefCount > 0) {
                      pixmap->release();                                         
                      currRefCount--;
                  }
              }
          }
      

      Attachments

        For Gerrit Dashboard: QTBUG-65077
        # Subject Branch Project Status CR V

        Activity

          People

            w00t Robin Burchell
            gunnar_roth gunnar_roth
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes