aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2016-09-09 16:20:57 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-10-06 14:46:21 +0000
commit57c9d6969ac474177c77d5ea59768b39620a3b2f (patch)
treed7fab7663b43af13f7551e9360a588594b7d21cf /src/qml/memory
parent6c05fe9cb760a9a26d7a1a8037aa62966a3bd344 (diff)
QML: Also check for correct destroy() chaining
Check that the destroy() method of Heap::Base was called when a Managed object needs destruction. This checks if a call to the parent's destroy() method was accidentally omitted. Change-Id: Id025ecd6d4744bf3eab23503fbe317ed2a461138 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory')
-rw-r--r--src/qml/memory/qv4heap_p.h34
-rw-r--r--src/qml/memory/qv4mm.cpp4
2 files changed, 31 insertions, 7 deletions
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index abbe85c04e..5a3797f397 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -133,19 +133,41 @@ struct Q_QML_EXPORT Base {
void *operator new(size_t, Heap::Base *m) { return m; }
void operator delete(void *, Heap::Base *) {}
- void init() { setInitialized(); }
+ void init() { _setInitialized(); }
+ void destroy() { _setDestroyed(); }
#ifdef QML_CHECK_INIT_DESTROY_CALLS
- bool _isInitialized;
+ enum { Uninitialized = 0, Initialized, Destroyed } _livenessStatus;
void _checkIsInitialized() {
- if (!_isInitialized)
+ if (_livenessStatus == Uninitialized)
fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n",
vtable()->className);
- Q_ASSERT(_isInitialized);
+ else if (_livenessStatus == Destroyed)
+ fprintf(stderr, "ERROR: use of object '%s' after call to destroy() !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus = Initialized);
+ }
+ void _checkIsDestroyed() {
+ if (_livenessStatus == Initialized)
+ fprintf(stderr, "ERROR: object '%s' was never destroyed completely !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus == Destroyed);
+ }
+ void _setInitialized() { Q_ASSERT(_livenessStatus == Uninitialized); _livenessStatus = Initialized; }
+ void _setDestroyed() {
+ if (_livenessStatus == Uninitialized)
+ fprintf(stderr, "ERROR: attempting to destroy an uninitialized object '%s' !!\n",
+ vtable()->className);
+ else if (_livenessStatus == Destroyed)
+ fprintf(stderr, "ERROR: attempting to destroy repeatedly object '%s' !!\n",
+ vtable()->className);
+ Q_ASSERT(_livenessStatus == Initialized);
+ _livenessStatus = Destroyed;
}
- void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; }
#else
Q_ALWAYS_INLINE void _checkIsInitialized() {}
- Q_ALWAYS_INLINE void setInitialized() {}
+ Q_ALWAYS_INLINE void _checkIsDestroyed() {}
+ Q_ALWAYS_INLINE void _setInitialized() {}
+ Q_ALWAYS_INLINE void _setDestroyed() {}
#endif
};
V4_ASSERT_IS_TRIVIAL(Base)
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 3d25bd1639..ad4ecfe76d 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -229,8 +229,10 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
*unmanagedHeapSize -= heapBytes;
}
- if (m->vtable()->destroy)
+ if (m->vtable()->destroy) {
m->vtable()->destroy(m);
+ m->_checkIsDestroyed();
+ }
memset(m, 0, header->itemSize);
#ifdef V4_USE_VALGRIND