summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2010-05-26 18:04:57 (GMT)
committerJoão Abecasis <joao.abecasis@nokia.com>2010-05-26 18:39:27 (GMT)
commit8060094144d6104659b8ce3b88d6f8b1e53cfb59 (patch)
tree46c192629f518c2f84fbda5199e3ab7e3882b5c2 /src
parentb7109e5ad32e6048b9051e4d5bccd88724d16d0e (diff)
downloadQt-8060094144d6104659b8ce3b88d6f8b1e53cfb59.zip
Qt-8060094144d6104659b8ce3b88d6f8b1e53cfb59.tar.gz
Qt-8060094144d6104659b8ce3b88d6f8b1e53cfb59.tar.bz2
Fix regression in QVarLengthArray::operator=
There was a serious regression wherei, under certain conditions, assignment would be treated as an append. This was due to poor tracking of container invariants inside realloc. From now on, after the allocation decision, s shall contain the number of elements in the array to be kept. Deleting extra elements in the old array needn't update this value. Instead, it needs to be updated once and if new elements are created afterwards. Auto-test greatly expanded to avoid future embarassments. Task-number: QTBUG-10978 Reviewed-by: Olivier Goffart Reviewed-by: Fabien Freling Olivier reviewed the patch, Fabien the auto-test.
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qvarlengtharray.h15
1 files changed, 7 insertions, 8 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index aecb66e..a70488f 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -128,9 +128,9 @@ private:
friend class QPodList<T, Prealloc>;
void realloc(int size, int alloc);
- int a;
- int s;
- T *ptr;
+ int a; // capacity
+ int s; // size
+ T *ptr; // data
union {
// ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
@@ -193,8 +193,8 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
Q_ASSERT(aalloc >= asize);
T *oldPtr = ptr;
int osize = s;
- // s = asize;
+ const int copySize = qMin(asize, osize);
if (aalloc != a) {
ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T)));
Q_CHECK_PTR(ptr);
@@ -205,7 +205,6 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
if (QTypeInfo<T>::isStatic) {
QT_TRY {
// copy all the old elements
- const int copySize = qMin(asize, osize);
while (s < copySize) {
new (ptr+s) T(*(oldPtr+s));
(oldPtr+s)->~T();
@@ -221,19 +220,19 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
QT_RETHROW;
}
} else {
- qMemCopy(ptr, oldPtr, qMin(asize, osize) * sizeof(T));
+ qMemCopy(ptr, oldPtr, copySize * sizeof(T));
}
} else {
ptr = oldPtr;
return;
}
}
+ s = copySize;
if (QTypeInfo<T>::isComplex) {
+ // destroy remaining old objects
while (osize > asize)
(oldPtr+(--osize))->~T();
- if (!QTypeInfo<T>::isStatic)
- s = osize;
}
if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)