diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-03-24 16:47:33 +0100 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2021-04-27 14:12:34 +0200 |
commit | 1f2d0cd983d08f1b8d791cb3674b0965d5e89f1a (patch) | |
tree | 40dbbc2cf53bc154c3758a2fb60f492d8b20d41d /src/corelib/tools/qlist.h | |
parent | 4b518d878aadb132256e8cea48fd6249667f59bb (diff) |
Resurrect data moves in QList
Use the data moves to readjust the free space in the QList,
which ultimately fixes the out-of-memory issues caused by
cases like:
forever {
list.prepend(list.back());
list.removeLast();
}
Task-number: QTBUG-91801
Task-number: QTBUG-91360
Task-number: QTBUG-93019
Change-Id: Iacff69cbf36b8b5b176bb2663df635ec972c875c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit a0253f5f0249024580050e4ec22d50cb139ef8d9)
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r-- | src/corelib/tools/qlist.h | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 6aafb86c01..ddce07bbb7 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -676,9 +676,10 @@ inline void QList<T>::resize_internal(qsizetype newSize) Q_ASSERT(newSize >= 0); if (d->needsDetach() || newSize > capacity() - d.freeSpaceAtBegin()) { - d.reallocateAndGrow(QArrayData::GrowsAtEnd, newSize - d.size); - } else if (newSize < size()) + d.detachAndGrow(QArrayData::GrowsAtEnd, newSize - d.size, nullptr, nullptr); + } else if (newSize < size()) { d->truncate(newSize); + } } template <typename T> @@ -761,12 +762,7 @@ inline T QList<T>::value(qsizetype i, parameter_type defaultValue) const template <typename T> inline void QList<T>::append(const_iterator i1, const_iterator i2) { - if (i1 == i2) - return; - const auto distance = std::distance(i1, i2); - DataPointer oldData; - d.detachAndGrow(QArrayData::GrowsAtEnd, distance, &oldData); - d->copyAppend(i1, i2); + d->growAppend(i1, i2); } template <typename T> @@ -778,7 +774,9 @@ inline void QList<T>::append(QList<T> &&other) if (other.d->needsDetach() || !std::is_nothrow_move_constructible_v<T>) return append(other); - d.detachAndGrow(QArrayData::GrowsAtEnd, other.size()); + // due to precondition &other != this, we can unconditionally modify 'this' + d.detachAndGrow(QArrayData::GrowsAtEnd, other.size(), nullptr, nullptr); + Q_ASSERT(d.freeSpaceAtEnd() >= other.size()); d->moveAppend(other.begin(), other.end()); } @@ -796,8 +794,9 @@ inline typename QList<T>::iterator QList<T>::insert(qsizetype i, qsizetype n, parameter_type t) { Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range"); - - d->insert(i, n, t); + Q_ASSERT_X(n >= 0, "QList::insert", "invalid count"); + if (Q_LIKELY(n)) + d->insert(i, n, t); return d.begin() + i; } |