Make QContiguousCache with zero capacity not crash
authorThiago Macieira <thiago.macieira@intel.com>
Tue, 25 Sep 2012 14:30:48 +0000 (16:30 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 19 Oct 2012 05:50:29 +0000 (07:50 +0200)
These containers don't make sense and will just result in no action
being taken (all items added will simply be discarded), but it
shouldn't crash due to a division by zero.

Update the documentation to explain the fact.

Task-number: QTBUG-27339
Change-Id: Ib9acf5c0a9a826e6853e7beaf5e56511fde98dc6
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Ian Walters <ian@walters.id.au>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/tools/qcontiguouscache.cpp
src/corelib/tools/qcontiguouscache.h
tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp

index 3e325be..40edb0f 100644 (file)
@@ -80,8 +80,15 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
     of matching how user interface views most commonly request data, as
     a set of rows localized around the current scrolled position.  This
     restriction allows the cache to consume less memory and processor
-    cycles than QCache.  The QContiguousCache class also can provide
-    an upper bound on memory usage via setCapacity().
+    cycles than QCache.
+
+    QContiguousCache operates on a fixed capacity, set with setCapacity() or
+    passed as a parameter to the constructor. This capacity is the upper bound
+    on memory usage by the cache itself, not including the memory allocated by
+    the elements themselves. Note that a cache with a capacity of zero (the
+    default) means no items will be stored: the insert(), append() and
+    prepend() operations will effectively be no-ops. Therefore, it's important
+    to set the capacity to a reasonable value before adding items to the cache.
 
     The simplest way of using a contiguous cache is to use the append()
     and prepend().
index 8713a34..e1cc65f 100644 (file)
@@ -341,6 +341,8 @@ void QContiguousCache<T>::freeData(Data *x)
 template <typename T>
 void QContiguousCache<T>::append(const T &value)
 {
+    if (!d->alloc)
+        return;     // zero capacity
     detach();
     if (QTypeInfo<T>::isComplex) {
         if (d->count == d->alloc)
@@ -362,6 +364,8 @@ void QContiguousCache<T>::append(const T &value)
 template<typename T>
 void QContiguousCache<T>::prepend(const T &value)
 {
+    if (!d->alloc)
+        return;     // zero capacity
     detach();
     if (d->start)
         d->start--;
@@ -385,6 +389,8 @@ template<typename T>
 void QContiguousCache<T>::insert(int pos, const T &value)
 {
     Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+    if (!d->alloc)
+        return;     // zero capacity
     detach();
     if (containsIndex(pos)) {
         if (QTypeInfo<T>::isComplex) {
index d6e8b87..f813a68 100644 (file)
@@ -67,6 +67,7 @@ private slots:
     void setCapacity();
 
     void zeroCapacity();
+    void modifyZeroCapacityCache();
 };
 
 QTEST_MAIN(tst_QContiguousCache)
@@ -365,4 +366,24 @@ void tst_QContiguousCache::zeroCapacity()
     QCOMPARE(contiguousCache.capacity(),0);
 }
 
+void tst_QContiguousCache::modifyZeroCapacityCache()
+{
+    {
+        QContiguousCache<int> contiguousCache;
+        contiguousCache.insert(0, 42);
+    }
+    {
+        QContiguousCache<int> contiguousCache;
+        contiguousCache.insert(1, 42);
+    }
+    {
+        QContiguousCache<int> contiguousCache;
+        contiguousCache.append(42);
+    }
+    {
+        QContiguousCache<int> contiguousCache;
+        contiguousCache.prepend(42);
+    }
+}
+
 #include "tst_qcontiguouscache.moc"