Fix array resize crash on 0 initialisation

This commit is contained in:
Doyle Thai 2018-01-04 16:27:50 +11:00
parent 8209593f57
commit 5876c16abe
2 changed files with 52 additions and 25 deletions

58
dqn.h
View File

@ -274,9 +274,9 @@ public:
typedef u8 *Allocator(DqnMemAPI::Request request); typedef u8 *Allocator(DqnMemAPI::Request request);
static Request RequestRealloc(const DqnMemAPI memAPI, void *const oldMemPtr, const size_t oldSize, const size_t newSize); static Request RequestRealloc(const DqnMemAPI memAPI, void *const oldMemPtr, size_t const oldSize, size_t const newSize);
static Request RequestAlloc (const DqnMemAPI memAPI, const size_t size, const bool clearToZero); static Request RequestAlloc (const DqnMemAPI memAPI, size_t const size, const bool clearToZero = true);
static Request RequestFree (const DqnMemAPI memAPI, void *const ptrToFree, const size_t sizeToFree); static Request RequestFree (const DqnMemAPI memAPI, void *const ptrToFree, size_t const sizeToFree);
bool IsValid() const { return (callback != nullptr); } bool IsValid() const { return (callback != nullptr); }
@ -349,17 +349,17 @@ struct DqnMemStack
// mem: Memory to use for the memory stack // mem: Memory to use for the memory stack
// byteAlign: Set the alignment of memory addresses for all allocated items from the memory stack. // byteAlign: Set the alignment of memory addresses for all allocated items from the memory stack.
// return: FALSE if args are invalid, or insufficient memSize. // return: FALSE if args are invalid, or insufficient memSize.
bool InitWithFixedMem(u8 *const mem, const size_t memSize, const u32 byteAlign_ = 4); bool InitWithFixedMem(u8 *const mem, size_t const memSize, u32 const byteAlign_ = 4);
// The memory stack uses 1 initial allocation from the DqnMem_Alloc(). No further allocations are // The memory stack uses 1 initial allocation from the DqnMem_Alloc(). No further allocations are
// made. All allocations are suballocated from the first allocation. // made. All allocations are suballocated from the first allocation.
// size: The amount of memory to allocate. Size gets aligned to the next "byteAlign"ed value. // size: The amount of memory to allocate. Size gets aligned to the next "byteAlign"ed value.
bool InitWithFixedSize(const size_t size, const bool zeroClear, const u32 byteAlign_ = 4, const DqnMemAPI memAPI_ = DqnMemAPI_HeapAllocator()); bool InitWithFixedSize(size_t const size, bool const zeroClear, u32 const byteAlign_ = 4, DqnMemAPI const memAPI_ = DqnMemAPI_HeapAllocator());
// Dynamically expandable stack. Akin to DqnMemStack_InitWithFixedSize() except if the MemStack does // Dynamically expandable stack. Akin to DqnMemStack_InitWithFixedSize() except if the MemStack does
// not have enough space for allocation it will automatically attach another MemBlock using // not have enough space for allocation it will automatically attach another MemBlock using
// DqnMem_Calloc(). // DqnMem_Calloc().
bool Init(const size_t size, const bool zeroClear, const u32 byteAlign_ = 4, const DqnMemAPI memAPI_ = DqnMemAPI_HeapAllocator()); bool Init(size_t const size, bool const zeroClear, u32 const byteAlign_ = 4, DqnMemAPI const memAPI_ = DqnMemAPI_HeapAllocator());
// -- Memory API // -- Memory API
// Allocate memory from the MemStack. // Allocate memory from the MemStack.
@ -382,7 +382,7 @@ struct DqnMemStack
bool FreeLastBlock(); bool FreeLastBlock();
// Reset the current memory block usage to 0. // Reset the current memory block usage to 0.
void ClearCurrBlock(const bool zeroClear); void ClearCurrBlock(bool const zeroClear);
// -- Temporary Regions API // -- Temporary Regions API
// region: Takes pointer to a zero-cleared DqnMemStackTempRegion struct. // region: Takes pointer to a zero-cleared DqnMemStackTempRegion struct.
@ -396,7 +396,7 @@ struct DqnMemStack
// -- Advanced API // -- Advanced API
// These are useful for forcing a new block to be used. AllocateCompatibleBlock() will fail if the // These are useful for forcing a new block to be used. AllocateCompatibleBlock() will fail if the
// supplied stack has flags set such that the stack is not allowed to have new blocks. // supplied stack has flags set such that the stack is not allowed to have new blocks.
Block *AllocateCompatibleBlock(size_t size, const bool zeroClear); Block *AllocateCompatibleBlock(size_t size, bool const zeroClear);
bool AttachBlock (Block *const newBlock); bool AttachBlock (Block *const newBlock);
bool DetachBlock (Block *const detachBlock); bool DetachBlock (Block *const detachBlock);
@ -639,8 +639,16 @@ bool DqnArray<T>::Resize(i64 newMax)
i64 oldSize = this->max * sizeof(T); i64 oldSize = this->max * sizeof(T);
i64 newSize = newMax * sizeof(T); i64 newSize = newMax * sizeof(T);
DqnMemAPI::Request info = DqnMemAPI::Request info;
DqnMemAPI::RequestRealloc(this->memAPI, this->data, oldSize, newSize); if (oldSize == 0)
{
info = DqnMemAPI::RequestAlloc(this->memAPI, newSize, /*zeroClear*/ false);
}
else
{
info = DqnMemAPI::RequestRealloc(this->memAPI, this->data, oldSize, newSize);
}
u8 *result = this->memAPI.callback(info); u8 *result = this->memAPI.callback(info);
if (result) if (result)
{ {
@ -3049,8 +3057,8 @@ FILE_SCOPE u8 *DqnMemAPIInternal_StackAllocatorCallback(DqnMemAPI::Request info)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnMemAPI Implementation // #DqnMemAPI Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DqnMemAPI::Request DqnMemAPI::RequestRealloc(const DqnMemAPI memAPI, void *const oldMemPtr, DqnMemAPI::Request DqnMemAPI::RequestRealloc(DqnMemAPI const memAPI, void *const oldMemPtr,
const size_t oldSize, const size_t newSize) size_t const oldSize, size_t const newSize)
{ {
DqnMemAPI::Request info = {}; DqnMemAPI::Request info = {};
info.type = Type::Realloc; info.type = Type::Realloc;
@ -3062,8 +3070,8 @@ DqnMemAPI::Request DqnMemAPI::RequestRealloc(const DqnMemAPI memAPI, void *const
return info; return info;
} }
DqnMemAPI::Request DqnMemAPI::RequestAlloc(const DqnMemAPI memAPI, const size_t size, DqnMemAPI::Request DqnMemAPI::RequestAlloc(DqnMemAPI const memAPI, size_t const size,
const bool clearToZero = true) bool const clearToZero)
{ {
DqnMemAPI::Request result = {}; DqnMemAPI::Request result = {};
result.type = DqnMemAPI::Type::Alloc; result.type = DqnMemAPI::Type::Alloc;
@ -3073,8 +3081,8 @@ DqnMemAPI::Request DqnMemAPI::RequestAlloc(const DqnMemAPI memAPI, const size_t
return result; return result;
} }
DqnMemAPI::Request DqnMemAPI::RequestFree(const DqnMemAPI memAPI, void *const ptrToFree, DqnMemAPI::Request DqnMemAPI::RequestFree(DqnMemAPI const memAPI, void *const ptrToFree,
const size_t sizeToFree) size_t const sizeToFree)
{ {
DqnMemAPI::Request result = {}; DqnMemAPI::Request result = {};
result.type = DqnMemAPI::Type::Free; result.type = DqnMemAPI::Type::Free;
@ -3105,8 +3113,8 @@ DQN_FILE_SCOPE DqnMemAPI DqnMemAPI_StackAllocator(DqnMemStack *const stack)
// #DqnMemStackInternal Implementation // #DqnMemStackInternal Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DqnMemStack::Block *DqnMemStackInternal_AllocateBlock(u32 byteAlign, size_t size, DQN_FILE_SCOPE DqnMemStack::Block *DqnMemStackInternal_AllocateBlock(u32 byteAlign, size_t size,
const bool zeroClear, bool const zeroClear,
const DqnMemAPI &memAPI) DqnMemAPI const &memAPI)
{ {
if (!memAPI.callback) return nullptr; if (!memAPI.callback) return nullptr;
@ -3129,8 +3137,8 @@ DQN_FILE_SCOPE DqnMemStack::Block *DqnMemStackInternal_AllocateBlock(u32 byteAli
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnMemStack Initialisation Implementation // #DqnMemStack Initialisation Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedMem(u8 *const mem, const size_t memSize, DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedMem(u8 *const mem, size_t const memSize,
const u32 byteAlign_) u32 const byteAlign_)
{ {
// TODO(doyle): Logging // TODO(doyle): Logging
if (!mem) return false; if (!mem) return false;
@ -3159,8 +3167,8 @@ DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedMem(u8 *const mem, const size_t me
return true; return true;
} }
DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedSize(size_t size, const bool zeroClear, DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedSize(size_t size, bool const zeroClear,
const u32 byteAlign_, const DqnMemAPI memAPI_) u32 const byteAlign_, DqnMemAPI const memAPI_)
{ {
bool result = this->Init(size, zeroClear, byteAlign_, memAPI_); bool result = this->Init(size, zeroClear, byteAlign_, memAPI_);
if (result) if (result)
@ -3173,7 +3181,7 @@ DQN_FILE_SCOPE bool DqnMemStack::InitWithFixedSize(size_t size, const bool zeroC
return false; return false;
} }
DQN_FILE_SCOPE bool DqnMemStack::Init(size_t size, const bool zeroClear, const u32 byteAlign_, const DqnMemAPI memAPI_) DQN_FILE_SCOPE bool DqnMemStack::Init(size_t size, bool const zeroClear, u32 const byteAlign_, DqnMemAPI const memAPI_)
{ {
if (!this || size < 0) return false; if (!this || size < 0) return false;
if (!DQN_ASSERT_MSG(!this->block, "MemStack has pre-existing block already attached")) if (!DQN_ASSERT_MSG(!this->block, "MemStack has pre-existing block already attached"))
@ -3331,7 +3339,7 @@ DQN_FILE_SCOPE bool DqnMemStack::FreeLastBlock()
return result; return result;
} }
DQN_FILE_SCOPE void DqnMemStack::ClearCurrBlock(const bool zeroClear) DQN_FILE_SCOPE void DqnMemStack::ClearCurrBlock(bool const zeroClear)
{ {
if (this->block) if (this->block)
{ {
@ -3396,7 +3404,7 @@ DqnMemStackTempRegionGuard::~DqnMemStackTempRegionGuard()
// #DqnMemStack Advanced API Implementation // #DqnMemStack Advanced API Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DqnMemStack::Block *DqnMemStack::AllocateCompatibleBlock(size_t size, DQN_FILE_SCOPE DqnMemStack::Block *DqnMemStack::AllocateCompatibleBlock(size_t size,
const bool zeroClear) bool const zeroClear)
{ {
if (this->flags & DqnMemStack::Flag::IsFixedMemoryFromUser) return nullptr; if (this->flags & DqnMemStack::Flag::IsFixedMemoryFromUser) return nullptr;
if (this->flags & DqnMemStack::Flag::IsNotExpandable) return nullptr; if (this->flags & DqnMemStack::Flag::IsNotExpandable) return nullptr;

View File

@ -1422,6 +1422,25 @@ void DqnArray_Test()
if (1) if (1)
{ {
if (1)
{
DqnArray<char> array1 = DqnArray_<char>(3);
DQN_ASSERT(array1.count == 0);
DQN_ASSERT(array1.max == 3);
array1.Free();
array1 = DqnArray_<char>();
DQN_ASSERT(array1.count == 0);
DQN_ASSERT(array1.max == 0);
array1.Push('c');
DQN_ASSERT(array1.count == 1);
DQN_ASSERT(array1.max == 1);
array1.Free();
LogSuccess("DqnArray(): Testing faux-array constructors DqnArray_()");
}
if (1) if (1)
{ {
DqnArray<char> array = {}; DqnArray<char> array = {};