From e6fc32a9c585b5a3369a3b889529bcc51f02396b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 2 Jul 2024 11:23:09 +0200 Subject: [PATCH] QArrayDataOps: fix appendUninitialized() ... to be strongly exception-safe and call placement new correctly. The old code could call user-provided overloads of new, because it didn't cast the pointer to void* before calling placement-new. It would also "randomly" stop when an exception was thrown. It correctly updated the size of the container only after successful construction of the element, but that's just weak exception-safety. There's no reason this operation shouldn't be strongly exception-safe. So instead of a raw loop around raw placement-new, use the corresponding raw memory STL algorithms. They handle exceptions and call placement-new correctly, and the code is both simpler as a consequence, and more efficient, as it updates this->size only once. Found in API-review. Amends 73bf1c1a9bcc2615370d6a199420da0c6f380a44. Change-Id: I535f393a3c378e1eea104bd3a05a274b9ec17964 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira (cherry picked from commit f699248c0f3ad44f09a422304870f40c1998a1a5) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/tools/qarraydataops.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index c3e9821e81a..6dcdba66195 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -969,15 +969,14 @@ public: Q_ASSERT(newSize > this->size); Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd()); - T *const b = this->begin(); - do { - auto ptr = b + this->size; - if constexpr (std::is_constructible_v) - new (ptr) T(Qt::Uninitialized); - else - new (ptr) T; // not T() -- default-construct - } while (++this->size != newSize); + T *const b = this->begin() + this->size; + T *const e = this->begin() + newSize; + if constexpr (std::is_constructible_v) + std::uninitialized_fill(b, e, Qt::Uninitialized); + else + std::uninitialized_default_construct(b, e); + this->size = newSize; } };