Fix illegal memory access on push_front, and merge push methods into one base function.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2825 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2009-11-10 09:51:13 +00:00
parent 007094898f
commit e2b8f785ca
1 changed files with 60 additions and 57 deletions

View File

@ -30,6 +30,7 @@ public:
{ {
} }
//! Constructs an array and allocates an initial chunk of memory. //! Constructs an array and allocates an initial chunk of memory.
/** \param start_count Amount of elements to pre-allocate. */ /** \param start_count Amount of elements to pre-allocate. */
array(u32 start_count) array(u32 start_count)
@ -48,7 +49,6 @@ public:
} }
//! Destructor. //! Destructor.
/** Frees allocated memory, if set_free_when_destroyed was not set to /** Frees allocated memory, if set_free_when_destroyed was not set to
false by the user before. */ false by the user before. */
@ -102,48 +102,13 @@ public:
strategy = newStrategy; strategy = newStrategy;
} }
//! Adds an element at back of array. //! Adds an element at back of array.
/** If the array is too small to add this new element it is made bigger. /** If the array is too small to add this new element it is made bigger.
\param element: Element to add at the back of the array. */ \param element: Element to add at the back of the array. */
void push_back(const T& element) void push_back(const T& element)
{ {
if (used + 1 > allocated) insert(element, used);
{
// this doesn't work if the element is in the same array. So
// we'll copy the element first to be sure we'll get no data
// corruption
T e(element);
//reallocate(used * 2 +1); // increase data block
// TA: okt, 2008. it's only allowed to alloc one element, if
// default constructor has to be called
// increase data block
u32 newAlloc;
switch ( strategy )
{
case ALLOC_STRATEGY_DOUBLE:
newAlloc = used + 1 + (allocated < 500 ?
(allocated < 5 ? 5 : used) : used >> 2);
break;
default:
case ALLOC_STRATEGY_SAFE:
newAlloc = used + 1;
break;
}
reallocate( newAlloc);
// construct new element
// Attention!. in missing default constructors for faster alloc methods
allocator.construct(&data[used++], e); // data[used++] = e; // push_back
}
else
{
//data[used++] = element;
// instead of using this here, we copy it the safe way:
allocator.construct(&data[used++], element);
}
is_sorted = false;
} }
@ -169,18 +134,55 @@ public:
_IRR_DEBUG_BREAK_IF(index>used) // access violation _IRR_DEBUG_BREAK_IF(index>used) // access violation
if (used + 1 > allocated) if (used + 1 > allocated)
reallocate(used +1);
for (u32 i=used; i>index; --i)
{ {
if (i<used) // this doesn't work if the element is in the same
allocator.destruct(&data[i]); // array. So we'll copy the element first to be sure
allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1]; // we'll get no data corruption
} const T e(element);
if (used > index) //reallocate(used * 2 +1); // increase data block
allocator.destruct(&data[index]); // TA: okt, 2008. it's only allowed to alloc one element, if
allocator.construct(&data[index], element); // data[index] = element; // default constructor has to be called
// increase data block
u32 newAlloc;
switch ( strategy )
{
case ALLOC_STRATEGY_DOUBLE:
newAlloc = used + 1 + (allocated < 500 ?
(allocated < 5 ? 5 : used) : used >> 2);
break;
default:
case ALLOC_STRATEGY_SAFE:
newAlloc = used + 1;
break;
}
reallocate( newAlloc);
// construct new element
for (u32 i=used; i>index; --i)
{
if (i<used)
allocator.destruct(&data[i]);
allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1];
}
if (used > index)
allocator.destruct(&data[index]);
allocator.construct(&data[index], e); // data[index] = e;
}
else
{
for (u32 i=used; i>index; --i)
{
if (i<used)
allocator.destruct(&data[i]);
allocator.construct(&data[i], data[i-1]); // data[i] = data[i-1];
}
if (used > index)
allocator.destruct(&data[index]);
allocator.construct(&data[index], element); // data[index] = element;
}
is_sorted = false; is_sorted = false;
++used; ++used;
} }
@ -279,6 +281,7 @@ public:
return true; return true;
} }
//! Inequality operator //! Inequality operator
bool operator != (const array<T>& other) const bool operator != (const array<T>& other) const
{ {
@ -473,6 +476,7 @@ public:
return index; return index;
} }
//! Finds an element in linear time, which is very slow. //! Finds an element in linear time, which is very slow.
/** Use binary_search for faster finding. Only works if ==operator is /** Use binary_search for faster finding. Only works if ==operator is
implemented. implemented.
@ -559,21 +563,20 @@ public:
is_sorted = _is_sorted; is_sorted = _is_sorted;
} }
private:
T* data; private:
u32 allocated; T* data;
u32 used; u32 allocated;
TAlloc allocator; u32 used;
eAllocStrategy strategy:4; TAlloc allocator;
bool free_when_destroyed:1; eAllocStrategy strategy:4;
bool is_sorted:1; bool free_when_destroyed:1;
bool is_sorted:1;
}; };
} // end namespace core } // end namespace core
} // end namespace irr } // end namespace irr
#endif #endif