From 85e2e72eb73ade7ab9e2ea07c99323c8af6cf2cb Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Wed, 11 Jun 2014 19:50:38 +0000 Subject: [PATCH] Fix TestHeaderless failure on GCC 4.9. Once 'delete' is called on an object, that object no longer exists, and accessing its member variables is undefined behaviour. GCC 4.9's optimiser recognises this, and eliminates any writes to member variables inside the destructor, since it knows they cannot legally be read later. BoundaryTagManager relied on ~FreedBlock resetting its memory to 0, so this optimisation broke it. Replace the placement new/delete with plain non-magic Setup/Reset functions, to avoid the optimisation. Fixes #2481. This was SVN commit r15334. --- source/lib/allocators/headerless.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/lib/allocators/headerless.cpp b/source/lib/allocators/headerless.cpp index f29a1e6d3d..b30e564139 100644 --- a/source/lib/allocators/headerless.cpp +++ b/source/lib/allocators/headerless.cpp @@ -54,12 +54,14 @@ public: { } - FreedBlock(uintptr_t id, size_t size) - : m_magic(s_magic), m_size(size), m_id(id) + void Setup(uintptr_t id, size_t size) { + m_magic = s_magic; + m_size = size; + m_id = id; } - ~FreedBlock() + void Reset() { // clear all fields to prevent accidental reuse prev = next = 0; @@ -410,8 +412,9 @@ public: FreedBlock* WriteTags(u8* p, size_t size) { - FreedBlock* freedBlock = new(p) FreedBlock(s_headerId, size); - (void)new(Footer(freedBlock)) FreedBlock(s_footerId, size); + FreedBlock* freedBlock = (FreedBlock*)p; + freedBlock->Setup(s_headerId, size); + Footer(freedBlock)->Setup(s_footerId, size); m_freeBlocks++; m_freeBytes += size; @@ -430,8 +433,8 @@ public: m_freeBytes -= freedBlock->Size(); FreedBlock* footer = Footer(freedBlock); - freedBlock->~FreedBlock(); - footer->~FreedBlock(); + freedBlock->Reset(); + footer->Reset(); } FreedBlock* PrecedingBlock(u8* p, u8* beginningOfPool) const