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

Document QHash element reference invalidation on rehash

    XMLWordPrintable

Details

    • All
    • 4c286d6f6 (dev), e38e517df (6.7)

    Description

      QHash::operator[] will return a reference to the value in the QHash for the specified key. However unlike std::unordered_map if the QHash is rehashed then that reference gets silently invalidated.

      This lead to a very tricky to track down issue for me where I was appending items to a QObjectList in a QHash while adding elements to the QHash and my QObjectList reference would seemingly magically loose all of its elements.

      Here is a reproduction case to illustrate the problem:

      #include <QtCore/QCoreApplication>
      #include <QtCore/QHash>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          QHash<QObject*, QList<int>> hash;
      
          constexpr size_t kQObjectCount = 1000;
      
          // I want to insert items into a reference to a list inside the QHash
          // at the same time as adding elements to the QHash.
          QObject* currentObject{nullptr};
      
          for (size_t i; i < 64; ++i) {
              currentObject = new QObject(&a);
              hash.insert(currentObject, {});
          }
      
          // Take a reference to a value in the hash.
          QList<int>& list = hash[currentObject];
          list.append(1);
          list.append(3);
          list.append(2);
          Q_ASSERT(hash.capacity() == 64);
      
          Q_ASSERT(list.contains(1));
          Q_ASSERT(list.contains(2));
          Q_ASSERT(list.contains(3));
      
          // Add one more object to the hash to cause a rehash.
          hash.insert(new QObject(&a), {});
          Q_ASSERT(hash.capacity() != 64);
      
          list.append(4);
          list.append(5);
          list.append(6);
      
          // I would expect the list to now contain 1, 2, 3, 4, 5 & 6
          // But it doesn't as the reference has been invalidated.
          Q_ASSERT(list.contains(1)); // <-- This fails.
          Q_ASSERT(list.contains(2));
          Q_ASSERT(list.contains(3));
          Q_ASSERT(list.contains(4));
          Q_ASSERT(list.contains(5));
          Q_ASSERT(list.contains(6));
      
          return 0;
      } 

      Either the reference invalidation should be documented somewhere (ideally under https://doc.qt.io/qt-6/qhash.html#operator-5b-5d) or QHash should not invalidate the reference on rehashing like std::unordered_map.

       

       

      Attachments

        1. main.cpp
          1 kB
          Ollie Dawes
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            manordheim Mårten Nordheim
            haiku Ollie Dawes
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes