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:
parent
548f50b071
commit
85e2e72eb7
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user