summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-05-24 17:29:10 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2022-05-01 04:42:18 +0200
commitfa20485f08daa6b57212c2a04bd3d7929368e59c (patch)
treecafa771ab94bdb7f3ae01c47dd2c8d583df4af06
parentc2cf1443430c642146ae14db9957f79e63a5ceb8 (diff)
QSharedPointer: Use matching new/delete
When a weak pointer calls getAndRef and there is no strong reference yet, getAndRef creates a new ExternalRefCountData. Normally, ExternalRefCountData is never constructed directly, only its subclasses are constructed via placement new into a memory buffer. To that end, ExternalRefCountData has a custom operator delete, which calls the global operator delete (do deallocate the memory buffer correctly). When using operator new directly in getAndRef, gcc notices a new/delete mismatch with the delete in the same function: global operator new matched with class operator delete. This isn't actually an issue in practice, as the class operator delete simply calls the global delete. But to avoid the warning, we can simply call the global operators explicitly. To make it clear that allocation of ExternalRefCountData requires some care, we additionally delete the class operator new, and only allow placement new (or usage of global operator new, as in getAndRef). Pick-to: 6.1 Task-number: QTBUG-93360 Change-Id: I132d1e4e07520eadc5b8f3f955c06aecec80c646 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 5e96c64afb274a3cc4364b1390ce0b776d637dd6) Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r--src/corelib/tools/qsharedpointer.cpp4
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h6
2 files changed, 8 insertions, 2 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 06df330dd9..7fe286fc5d 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -1400,7 +1400,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
}
// we can create the refcount data because it doesn't exist
- ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
+ ExternalRefCountData *x = ::new ExternalRefCountData(Qt::Uninitialized);
x->strongref.storeRelaxed(-1);
x->weakref.storeRelaxed(2); // the QWeakPointer that called us plus the QObject itself
@@ -1411,7 +1411,7 @@ QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::ge
// ~ExternalRefCountData has a Q_ASSERT, so we use this trick to
// only execute this if Q_ASSERTs are enabled
Q_ASSERT((x->weakref.storeRelaxed(0), true));
- delete x;
+ ::delete x;
ret->weakref.ref();
}
return ret;
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index f05adf8fc5..0b1960eafc 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -156,6 +156,12 @@ namespace QtSharedPointer {
inline void checkQObjectShared(...) { }
inline void setQObjectShared(...) { }
+ // Normally, only subclasses of ExternalRefCountData are allocated
+ // One exception exists in getAndRef; that uses the global operator new
+ // to prevent a mismatch with the custom operator delete
+ inline void *operator new(std::size_t) = delete;
+ // placement new
+ inline void *operator new(std::size_t, void *ptr) noexcept { return ptr; }
inline void operator delete(void *ptr) { ::operator delete(ptr); }
inline void operator delete(void *, void *) { }
};