diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-09-09 16:20:57 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-10-06 14:46:21 +0000 |
commit | 57c9d6969ac474177c77d5ea59768b39620a3b2f (patch) | |
tree | d7fab7663b43af13f7551e9360a588594b7d21cf /src/qml/memory | |
parent | 6c05fe9cb760a9a26d7a1a8037aa62966a3bd344 (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.h | 34 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 4 |
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 |