diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-03-24 16:47:33 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-04-27 07:39:49 +0000 |
commit | 8e95bba272bc2aadc2e2dd4ad66dab489cb70387 (patch) | |
tree | 3c07b75d4b9460e4e26e9d1b37c88a682f389127 /src/corelib/text | |
parent | ad496ea3b5ae79172af3a0231a65ae7c7ee44492 (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)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/corelib/text')
-rw-r--r-- | src/corelib/text/qbytearray.cpp | 19 | ||||
-rw-r--r-- | src/corelib/text/qstring.cpp | 49 |
2 files changed, 27 insertions, 41 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 045d8a73b4..23e295405f 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -1956,8 +1956,7 @@ QByteArray &QByteArray::append(const QByteArray &ba) QByteArray& QByteArray::append(char ch) { - if (d->needsDetach() || !d->freeSpaceAtEnd()) - reallocGrowData(1); + d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr); d->copyAppend(1, ch); d.data()[d.size] = '\0'; return *this; @@ -1997,12 +1996,8 @@ QByteArray &QByteArray::insert(qsizetype i, QByteArrayView data) // defer a call to free() so that it comes after we copied the data from // the old memory: DataPointer detached{}; // construction is free - if (d->needsDetach() || i + size - d->size > d.freeSpaceAtEnd()) { - detached = DataPointer::allocateGrow(d, i + size - d->size, Data::GrowsAtEnd); - Q_CHECK_PTR(detached.data()); - detached->copyAppend(d.constBegin(), d.constEnd()); - d.swap(detached); - } + d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + size, &str, &detached); + Q_CHECK_PTR(d.data()); d->copyAppend(i - d->size, ' '); d->copyAppend(str, str + size); d.data()[d.size] = '\0'; @@ -2079,12 +2074,8 @@ QByteArray &QByteArray::insert(qsizetype i, qsizetype count, char ch) if (i >= d->size) { // handle this specially, as QArrayDataOps::insert() doesn't handle out of bounds positions - if (d->needsDetach() || i + count - d->size > d.freeSpaceAtEnd()) { - DataPointer detached(DataPointer::allocateGrow(d, i + count - d->size, Data::GrowsAtEnd)); - Q_CHECK_PTR(detached.data()); - detached->copyAppend(d.constBegin(), d.constEnd()); - d.swap(detached); - } + d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + count, nullptr, nullptr); + Q_CHECK_PTR(d.data()); d->copyAppend(i - d->size, ' '); d->copyAppend(count, ch); d.data()[d.size] = '\0'; diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index c2af431c94..89957e5cb6 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2760,13 +2760,17 @@ QString &QString::insert(qsizetype i, QLatin1String str) return *this; qsizetype len = str.size(); + qsizetype difference = 0; if (Q_UNLIKELY(i > size())) - resize(i + len, QLatin1Char(' ')); - else - resize(size() + len); + difference = i - size(); + d.detachAndGrow(Data::GrowsAtEnd, difference + len, nullptr, nullptr); + Q_CHECK_PTR(d.data()); + d->copyAppend(difference, u' '); + d.size += len; ::memmove(d.data() + i + len, d.data() + i, (d.size - i - len) * sizeof(QChar)); qt_from_latin1(d.data() + i, s, size_t(len)); + d.data()[d.size] = u'\0'; return *this; } @@ -2787,7 +2791,7 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size) if (i < 0 || size <= 0) return *this; - const auto s = reinterpret_cast<const char16_t *>(unicode); + const char16_t *s = reinterpret_cast<const char16_t *>(unicode); // handle this specially, as QArrayDataOps::insert() doesn't handle out of // bounds positions @@ -2796,12 +2800,8 @@ QString& QString::insert(qsizetype i, const QChar *unicode, qsizetype size) // defer a call to free() so that it comes after we copied the data from // the old memory: DataPointer detached{}; // construction is free - if (d->needsDetach() || i + size - d->size > d.freeSpaceAtEnd()) { - detached = DataPointer::allocateGrow(d, i + size - d->size, Data::GrowsAtEnd); - Q_CHECK_PTR(detached.data()); - detached->copyAppend(d.constBegin(), d.constEnd()); - d.swap(detached); - } + d.detachAndGrow(Data::GrowsAtEnd, (i - d.size) + size, &s, &detached); + Q_CHECK_PTR(d.data()); d->copyAppend(i - d->size, u' '); d->copyAppend(s, s + size); d.data()[d.size] = u'\0'; @@ -2857,11 +2857,8 @@ QString &QString::append(const QString &str) if (!str.isNull()) { if (isNull()) { operator=(str); - } else { - if (d->needsDetach() || str.size() > d->freeSpaceAtEnd()) - reallocGrowData(str.size()); - d->copyAppend(str.d.data(), str.d.data() + str.d.size); - d.data()[d.size] = '\0'; + } else if (str.size()) { + append(str.constData(), str.size()); } } return *this; @@ -2876,13 +2873,11 @@ QString &QString::append(const QString &str) QString &QString::append(const QChar *str, qsizetype len) { if (str && len > 0) { - if (d->needsDetach() || len > d->freeSpaceAtEnd()) - reallocGrowData(len); static_assert(sizeof(QChar) == sizeof(char16_t), "Unexpected difference in sizes"); // the following should be safe as QChar uses char16_t as underlying data const char16_t *char16String = reinterpret_cast<const char16_t *>(str); - d->copyAppend(char16String, char16String + len); - d.data()[d.size] = '\0'; + d->growAppend(char16String, char16String + len); + d.data()[d.size] = u'\0'; } return *this; } @@ -2895,16 +2890,17 @@ QString &QString::append(const QChar *str, qsizetype len) QString &QString::append(QLatin1String str) { const char *s = str.latin1(); - if (s) { - qsizetype len = str.size(); - if (d->needsDetach() || str.size() > d->freeSpaceAtEnd()) - reallocGrowData(len); - - Q_ASSERT(str.size() <= d->freeSpaceAtEnd()); + const qsizetype len = str.size(); + if (s && len > 0) { + d.detachAndGrow(Data::GrowsAtEnd, len, nullptr, nullptr); + Q_CHECK_PTR(d.data()); + Q_ASSERT(len <= d->freeSpaceAtEnd()); char16_t *i = d.data() + d.size; qt_from_latin1(i, s, size_t(len)); d.size += len; d.data()[d.size] = '\0'; + } else if (d.isNull() && !str.isNull()) { // special case + d = DataPointer::fromRawData(&_empty, 0); } return *this; } @@ -2942,8 +2938,7 @@ QString &QString::append(QLatin1String str) */ QString &QString::append(QChar ch) { - if (d->needsDetach() || !d->freeSpaceAtEnd()) - reallocGrowData(1); + d.detachAndGrow(QArrayData::GrowsAtEnd, 1, nullptr, nullptr); d->copyAppend(1, ch.unicode()); d.data()[d.size] = '\0'; return *this; |