1
0
forked from 0ad/0ad

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.
This commit is contained in:
Ykkrosh 2014-06-11 19:50:38 +00:00
parent 548f50b071
commit 85e2e72eb7

View File

@ -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