diff --git a/Recast/Include/RecastAlloc.h b/Recast/Include/RecastAlloc.h index a048e28..a3c5fbd 100644 --- a/Recast/Include/RecastAlloc.h +++ b/Recast/Include/RecastAlloc.h @@ -73,7 +73,7 @@ typedef intptr_t rcSizeType; #define RC_SIZE_MAX INTPTR_MAX /// Macros to hint to the compiler about the likeliest branch. Please add a benchmark that demonstrates a performance -/// improvement before intrudcing use cases. +/// improvement before introducing use cases. #if defined(__GNUC__) || defined(__clang__) #define rcLikely(x) __builtin_expect((x), true) #define rcUnlikely(x) __builtin_expect((x), false) @@ -116,7 +116,8 @@ class rcVectorBase { rcVectorBase(const T* begin, const T* end) : m_size(0), m_cap(0), m_data(0) { assign(begin, end); } ~rcVectorBase() { destroy_range(0, m_size); rcFree(m_data); } - void reserve(rcSizeType size); + // Unlike in std::vector, we return a bool to indicate whether the alloc was successful. + bool reserve(rcSizeType size); void assign(rcSizeType count, const T& value) { clear(); resize(count, value); } void assign(const T* begin, const T* end); @@ -155,21 +156,27 @@ class rcVectorBase { }; template -void rcVectorBase::reserve(rcSizeType count) { +bool rcVectorBase::reserve(rcSizeType count) { if (count <= m_cap) { - return; + return true; } T* new_data = allocate_and_copy(count); + if (!new_data) { + return false; + } destroy_range(0, m_size); rcFree(m_data); m_data = new_data; m_cap = count; + return true; } template T* rcVectorBase::allocate_and_copy(rcSizeType size) { rcAssert(RC_SIZE_MAX / sizeof(T) >= size); T* new_data = static_cast(rcAlloc(sizeof(T) * size, H)); - copy_range(new_data, m_data, m_data + m_size); + if (new_data) { + copy_range(new_data, m_data, m_data + m_size); + } return new_data; } template diff --git a/Recast/Source/RecastRegion.cpp b/Recast/Source/RecastRegion.cpp index 2b721a7..e1fc0ee 100644 --- a/Recast/Source/RecastRegion.cpp +++ b/Recast/Source/RecastRegion.cpp @@ -25,7 +25,6 @@ #include "Recast.h" #include "RecastAlloc.h" #include "RecastAssert.h" -#include namespace { @@ -796,16 +795,15 @@ static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRe const int h = chf.height; const int nreg = maxRegionId+1; - rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); - if (!regions) - { + rcTempVector regions; + if (!regions.reserve(nreg)) { ctx->log(RC_LOG_ERROR, "mergeAndFilterRegions: Out of memory 'regions' (%d).", nreg); return false; } // Construct regions for (int i = 0; i < nreg; ++i) - new(®ions[i]) rcRegion((unsigned short)i); + regions.push_back(rcRegion((unsigned short) i)); // Find edge of a region and find connections around the contour. for (int y = 0; y < h; ++y) @@ -1031,11 +1029,6 @@ static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRe if (regions[i].overlap) overlaps.push(regions[i].id); - for (int i = 0; i < nreg; ++i) - regions[i].~rcRegion(); - rcFree(regions); - - return true; } @@ -1057,16 +1050,15 @@ static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea, const int h = chf.height; const int nreg = maxRegionId+1; - rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); - if (!regions) - { + rcTempVector regions; + + // Construct regions + if (!regions.reserve(nreg)) { ctx->log(RC_LOG_ERROR, "mergeAndFilterLayerRegions: Out of memory 'regions' (%d).", nreg); return false; } - - // Construct regions for (int i = 0; i < nreg; ++i) - new(®ions[i]) rcRegion((unsigned short)i); + regions.push_back(rcRegion((unsigned short) i)); // Find region neighbours and overlapping regions. rcIntArray lregs(32); @@ -1244,10 +1236,6 @@ static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea, srcReg[i] = regions[srcReg[i]].id; } - for (int i = 0; i < nreg; ++i) - regions[i].~rcRegion(); - rcFree(regions); - return true; }