diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-07-30 13:28:49 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-07-30 13:28:49 (GMT) |
commit | a08b3f5336e5c819b33d922d3a809b5203d728f3 (patch) | |
tree | 952f42304d50f28ed6651bace587ab7935b29cd0 /src/corelib/tools | |
parent | 813fc3574a006cb2687715ccf7bdb984a485b173 (diff) | |
parent | 188ac02e2fb6cc6437b776f8c5b69a508728fbdb (diff) | |
download | Qt-a08b3f5336e5c819b33d922d3a809b5203d728f3.zip Qt-a08b3f5336e5c819b33d922d3a809b5203d728f3.tar.gz Qt-a08b3f5336e5c819b33d922d3a809b5203d728f3.tar.bz2 |
Merge commit 'qt/master-stable'
Conflicts:
demos/demos.pro
src/gui/graphicsview/qgraphicsitem_p.h
Diffstat (limited to 'src/corelib/tools')
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 113 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer_impl.h | 37 |
2 files changed, 107 insertions, 43 deletions
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 596a125..a186771 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -808,29 +808,19 @@ # endif # endif -# if !defined(BACKTRACE_SUPPORTED) -// Dummy implementation of the functions. -// Using QHashDummyValue also means that the QHash below is actually a QSet -typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace; - -static inline Backtrace saveBacktrace() { return Backtrace(); } -static inline void printBacktrace(Backtrace) { } - -# else +# if defined(BACKTRACE_SUPPORTED) # include <sys/types.h> # include <execinfo.h> # include <stdio.h> # include <unistd.h> # include <sys/wait.h> -typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace; - -static inline Backtrace saveBacktrace() __attribute__((always_inline)); -static inline Backtrace saveBacktrace() +static inline QByteArray saveBacktrace() __attribute__((always_inline)); +static inline QByteArray saveBacktrace() { static const int maxFrames = 32; - Backtrace stacktrace; + QByteArray stacktrace; stacktrace.resize(sizeof(void*) * maxFrames); int stack_size = backtrace((void**)stacktrace.data(), maxFrames); stacktrace.resize(sizeof(void*) * stack_size); @@ -838,7 +828,7 @@ static inline Backtrace saveBacktrace() return stacktrace; } -static void printBacktrace(Backtrace stacktrace) +static void printBacktrace(QByteArray stacktrace) { void *const *stack = (void *const *)stacktrace.constData(); int stack_size = stacktrace.size() / sizeof(void*); @@ -889,11 +879,19 @@ static void printBacktrace(Backtrace stacktrace) namespace { QT_USE_NAMESPACE + struct Data { + const volatile void *pointer; +# ifdef BACKTRACE_SUPPORTED + QByteArray backtrace; +# endif + }; + class KnownPointers { public: QMutex mutex; - QHash<void *, Backtrace> values; + QHash<const void *, Data> dPointers; + QHash<const volatile void *, const void *> dataPointers; }; } @@ -901,38 +899,101 @@ Q_GLOBAL_STATIC(KnownPointers, knownPointers) QT_BEGIN_NAMESPACE +namespace QtSharedPointer { + Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckAdd(const volatile void *) +{ + // Qt 4.5 compatibility + // this function is broken by design, so it was replaced with internalSafetyCheckAdd2 + // + // it's broken because we tracked the pointers added and + // removed from QSharedPointer, converted to void*. + // That is, this is supposed to track the "top-of-object" pointer in + // case of multiple inheritance. + // + // However, it doesn't work well in some compilers: + // if you create an object with a class of type A and the last reference + // is dropped of type B, then the value passed to internalSafetyCheckRemove could + // be different than was added. That would leave dangling addresses. + // + // So instead, we track the pointer by the d-pointer instead. +} + /*! \internal */ -void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckRemove(const volatile void *) { + // Qt 4.5 compatibility + // see comments above +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckAdd2(const void *d_ptr, const volatile void *ptr) +{ + // see comments above for the rationale for this function KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - if (kp->values.contains(actual)) { - printBacktrace(knownPointers()->values.value(actual)); - qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked " - "by another QSharedPointerData object", actual); + Q_ASSERT(!kp->dPointers.contains(d_ptr)); + + //qDebug("Adding d=%p value=%p", d_ptr, ptr); + + const void *other_d_ptr = kp->dataPointers.value(ptr, 0); + if (other_d_ptr) { +# ifdef BACKTRACE_SUPPORTED + printBacktrace(knownPointers()->dPointers.value(other_d_ptr).backtrace); +# endif + qFatal("QSharedPointer: internal self-check failed: pointer %p was already tracked " + "by another QSharedPointer object %p", ptr, other_d_ptr); } - kp->values.insert(actual, saveBacktrace()); + Data data; + data.pointer = ptr; +# ifdef BACKTRACE_SUPPORTED + data.backtrace = saveBacktrace(); +# endif + + kp->dPointers.insert(d_ptr, data); + kp->dataPointers.insert(ptr, d_ptr); } /*! \internal */ -void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr) +void QtSharedPointer::internalSafetyCheckRemove2(const void *d_ptr) { KnownPointers *const kp = knownPointers(); if (!kp) return; // end-game: the application is being destroyed already QMutexLocker lock(&kp->mutex); - void *actual = const_cast<void*>(ptr); - kp->values.remove(actual); + + QHash<const void *, Data>::iterator it = kp->dPointers.find(d_ptr); + if (it == kp->dPointers.end()) { + qFatal("QSharedPointer: internal self-check inconsistency: pointer %p was not tracked. " + "To use QT_SHAREDPOINTER_TRACK_POINTERS, you have to enable it throughout " + "in your code.", d_ptr); + } + + QHash<const volatile void *, const void *>::iterator it2 = kp->dataPointers.find(it->pointer); + Q_ASSERT(it2 != kp->dataPointers.end()); + + //qDebug("Removing d=%p value=%p", d_ptr, it->pointer); + + // remove entries + kp->dataPointers.erase(it2); + kp->dPointers.erase(it); } QT_END_NAMESPACE diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index d9fc73c..657c45a 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -98,9 +98,9 @@ namespace QtSharedPointer { template <class X, class Y> QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); // used in debug mode to verify the reuse of pointers - Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); - Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); - + Q_CORE_EXPORT void internalSafetyCheckAdd2(const void *, const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove2(const void *); + template <class T, typename Klass, typename RetVal> inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)()) { (t->*memberDeleter)(); } @@ -152,17 +152,8 @@ namespace QtSharedPointer { inline void internalConstruct(T *ptr) { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (ptr) internalSafetyCheckAdd(ptr); -#endif value = ptr; } - inline void internalDestroy() - { -#ifdef QT_SHAREDPOINTER_TRACK_POINTERS - if (value) internalSafetyCheckRemove(value); -#endif - } #if defined(Q_NO_TEMPLATE_FRIENDS) public: @@ -241,7 +232,6 @@ namespace QtSharedPointer { struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn { typedef ExternalRefCountWithDestroyFn Parent; - typedef ExternalRefCountWithContiguousData Self; T data; static void deleter(ExternalRefCountData *self) @@ -254,7 +244,8 @@ namespace QtSharedPointer { static inline ExternalRefCountData *create(T **ptr) { DestroyerFn destroy = &deleter; - Self *d = static_cast<Self *>(::operator new(sizeof(Self))); + ExternalRefCountWithContiguousData *d = + static_cast<ExternalRefCountWithContiguousData *>(::operator new(sizeof(ExternalRefCountWithContiguousData))); // initialize the d-pointer sub-object // leave d->data uninitialized @@ -279,8 +270,9 @@ namespace QtSharedPointer { inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline bool deref() { - if (!d->strongref.deref()) - this->internalDestroy(); + if (!d->strongref.deref()) { + internalDestroy(); + } return d->weakref.deref(); } @@ -290,6 +282,9 @@ namespace QtSharedPointer { Q_ASSERT(!d); if (ptr) d = new Data; +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd2(d, ptr); +#endif } template <typename Deleter> @@ -299,6 +294,9 @@ namespace QtSharedPointer { Q_ASSERT(!d); if (ptr) d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd2(d, ptr); +#endif } inline void internalCreate() @@ -307,6 +305,9 @@ namespace QtSharedPointer { d = ExternalRefCountWithContiguousData<T>::create(&ptr); Basic<T>::internalConstruct(ptr); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + if (ptr) internalSafetyCheckAdd2(d, ptr); +#endif } inline ExternalRefCount() : d(0) { } @@ -322,7 +323,9 @@ namespace QtSharedPointer { inline void internalDestroy() { - Basic<T>::internalDestroy(); +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS + internalSafetyCheckRemove2(d); +#endif if (!d->destroy()) delete this->value; } |