diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 74784af1212..41cf9abc467 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -247,14 +247,15 @@ public: if (result.initialized) { cost -= n->value.cost; result.it.node()->emplace(object, cost); + relink(key); } else { Node::createInPlace(n, key, object, cost); + n->prev = &chain; + n->next = chain.next; + chain.next->prev = n; + chain.next = n; } total += cost; - n->prev = &chain; - n->next = chain.next; - chain.next->prev = n; - chain.next = n; return true; } T *object(const Key &key) const noexcept diff --git a/tests/auto/corelib/tools/qcache/tst_qcache.cpp b/tests/auto/corelib/tools/qcache/tst_qcache.cpp index f122e45e876..54cf00f9da5 100644 --- a/tests/auto/corelib/tools/qcache/tst_qcache.cpp +++ b/tests/auto/corelib/tools/qcache/tst_qcache.cpp @@ -48,6 +48,7 @@ private slots: void take(); void axioms_on_key_type(); void largeCache(); + void internalChainOrderAfterEntryUpdate(); }; @@ -414,5 +415,21 @@ void tst_QCache::largeCache() QVERIFY(cache.size() == 0); } +// The internal chain could lose track of some objects. +// Make sure it doesn't happen again. +void tst_QCache::internalChainOrderAfterEntryUpdate() +{ + QCache cache; + cache.setMaxCost(20); + cache.insert(QString::number(1), new int, 1); + cache.insert(QString::number(2), new int, 1); + cache.insert(QString::number(1), new int, 1); + // If the chain is still 'in order' then setting maxCost == 0 should + // a. not crash, and + // b. remove all the elements in the QHash + cache.setMaxCost(0); + QCOMPARE(cache.size(), 0); +} + QTEST_APPLESS_MAIN(tst_QCache) #include "tst_qcache.moc"