mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-05 18:16:23 +03:00
0026287: Bug in NCollection_AccAllocator::Free() sometimes causes crash in debug mode
This commit is contained in:
parent
db2f149828
commit
7c47a3d647
@ -97,7 +97,7 @@ void NCollection_AccAllocator::Free(void* theAddress)
|
||||
Block* aBlock = findBlock(theAddress, aKey);
|
||||
|
||||
#if !defined No_Exception && !defined No_Standard_ProgramError
|
||||
if (aBlock == 0L || aBlock->allocCount == 0)
|
||||
if (aBlock == 0L || aBlock->IsEmpty())
|
||||
{
|
||||
Standard_ProgramError::Raise("NCollection_AccAllocator::Free: \
|
||||
Trying to free an invalid address");
|
||||
@ -105,7 +105,7 @@ void NCollection_AccAllocator::Free(void* theAddress)
|
||||
#endif
|
||||
|
||||
aBlock->Free();
|
||||
if (aBlock->allocCount == 0)
|
||||
if (aBlock->IsEmpty())
|
||||
{
|
||||
Standard_Address anAddress = aBlock->address;
|
||||
|
||||
@ -129,13 +129,38 @@ void NCollection_AccAllocator::Free(void* theAddress)
|
||||
// If there are no more blocks, reallocate the block to the default size
|
||||
else
|
||||
{
|
||||
anAddress = Standard::Reallocate(anAddress, myBlockSize);
|
||||
if (anAddress)
|
||||
Standard_Address aNewAddress = Standard::Reallocate(anAddress,
|
||||
myBlockSize);
|
||||
if (aNewAddress == anAddress)
|
||||
{
|
||||
aBlock->address = anAddress;
|
||||
// Normally, the reallocation keeps the block at the same address
|
||||
// (since no block can be smaller than the default size, and thus
|
||||
// the allocated memory is just shrunk or untouched).
|
||||
// In this case, just update the block's free size.
|
||||
aBlock->SetFreeSize(myBlockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reallocation still may return a different address even if the new
|
||||
// size is equal to or smaller than the old one (this can happen in
|
||||
// debug mode).
|
||||
Key aNewKey = getKey(aNewAddress);
|
||||
if (aNewKey.Value == aKey.Value)
|
||||
{
|
||||
// If the new address have the same key,
|
||||
// just update the block's address and free size
|
||||
aBlock->address = aNewAddress;
|
||||
aBlock->SetFreeSize(myBlockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the new address have different key,
|
||||
// rebind the block to the map of blocks with the new key.
|
||||
myBlocks.Clear(Standard_False);
|
||||
mypLastBlock = myBlocks.Bound(aNewKey,
|
||||
Block(aNewAddress, myBlockSize));
|
||||
}
|
||||
}
|
||||
aBlock->allocStart = (Standard_Byte*)anAddress
|
||||
+ (Standard_Size)myBlockSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,15 +201,13 @@ NCollection_AccAllocator::allocateNewBlock(const Standard_Size theSize)
|
||||
Standard_Address anAddress = Standard::Allocate(theSize);
|
||||
// we depend on the fact that Standard::Allocate always returns
|
||||
// a pointer aligned to a 4 byte boundary
|
||||
Block aBlock = {anAddress,
|
||||
AlignedPtr((Standard_Byte*)anAddress + theSize),
|
||||
mypLastBlock,
|
||||
0};
|
||||
mypLastBlock = myBlocks.Bound(getKey(anAddress), aBlock);
|
||||
mypLastBlock = myBlocks.Bound(getKey(anAddress),
|
||||
Block(anAddress, theSize, mypLastBlock));
|
||||
#ifdef OCCT_DEBUG_FINDBLOCK
|
||||
Key aKey;
|
||||
Standard_ASSERT_VOID(mypLastBlock == findBlock((Standard_Byte*)aBlock.allocStart-1, aKey),
|
||||
"improper work of NCollection_AccAllocator::findBlock");
|
||||
Standard_ASSERT_VOID(
|
||||
mypLastBlock == findBlock((Standard_Byte*)mypLastBlock->allocStart-1, aKey),
|
||||
"improper work of NCollection_AccAllocator::findBlock");
|
||||
#endif
|
||||
return mypLastBlock;
|
||||
}
|
||||
|
@ -106,7 +106,8 @@ protected:
|
||||
|
||||
//! A key for the map of blocks
|
||||
struct Key {Standard_Size Value;};
|
||||
//! AccAllocator hasher
|
||||
|
||||
//! Key hasher
|
||||
class Hasher
|
||||
{
|
||||
public:
|
||||
@ -125,6 +126,15 @@ protected:
|
||||
Block* prevBlock;
|
||||
Standard_Integer allocCount;
|
||||
|
||||
Block(const Standard_Address theAddress,
|
||||
const Standard_Size theSize,
|
||||
Block* thePrevBlock = 0L)
|
||||
: address(theAddress), prevBlock(thePrevBlock), allocCount(0)
|
||||
{SetFreeSize (theSize);}
|
||||
|
||||
void SetFreeSize(const Standard_Size theSize)
|
||||
{allocStart = (Standard_Byte*)address + theSize;}
|
||||
|
||||
Standard_Size FreeSize() const
|
||||
{return (Standard_Byte*)allocStart - (Standard_Byte*)address;}
|
||||
|
||||
@ -133,6 +143,9 @@ protected:
|
||||
|
||||
void Free()
|
||||
{allocCount--;}
|
||||
|
||||
Standard_Boolean IsEmpty() const
|
||||
{return allocCount == 0;}
|
||||
};
|
||||
|
||||
// --------- PROTECTED METHODS ---------
|
||||
|
Loading…
x
Reference in New Issue
Block a user