summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-07-30 13:28:49 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-07-30 13:28:49 (GMT)
commita08b3f5336e5c819b33d922d3a809b5203d728f3 (patch)
tree952f42304d50f28ed6651bace587ab7935b29cd0 /src/corelib/tools
parent813fc3574a006cb2687715ccf7bdb984a485b173 (diff)
parent188ac02e2fb6cc6437b776f8c5b69a508728fbdb (diff)
downloadQt-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.cpp113
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h37
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;
}