- SF#3540497 HashMap iterator crash in VS 2010

- allow Buffer resize to zero
This commit is contained in:
Aleksandar Fabijanic 2012-08-04 03:49:51 +00:00
parent b2b18b07a5
commit 5cade11ba6
4 changed files with 30 additions and 13 deletions

View File

@ -126,10 +126,12 @@ public:
} }
void resize(std::size_t newCapacity, bool preserveContent = true) void resize(std::size_t newCapacity, bool preserveContent = true)
/// Resizes the buffer. If preserveContent is true, /// Resizes the buffer capacity and size. If preserveContent is true,
/// the content of the old buffer is copied over to the /// the content of the old buffer is copied over to the
/// new buffer. The new capacity can be larger or smaller than /// new buffer. The new capacity can be larger or smaller than
/// the current one, but it must not be 0. /// the current one; if it is smaller, capacity will remain intact.
/// Size will always be set to the new capacity.
///
/// Buffers only wrapping externally owned storage can not be /// Buffers only wrapping externally owned storage can not be
/// resized. If resize is attempted on those, IllegalAccessException /// resized. If resize is attempted on those, IllegalAccessException
/// is thrown. /// is thrown.
@ -137,8 +139,6 @@ public:
if (!_ownMem) if (!_ownMem)
throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage."); throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
poco_assert(newCapacity);
if (newCapacity > _capacity) if (newCapacity > _capacity)
{ {
T* ptr = new T[newCapacity]; T* ptr = new T[newCapacity];

View File

@ -92,21 +92,24 @@ public:
class ConstIterator: public std::iterator<std::forward_iterator_tag, Value> class ConstIterator: public std::iterator<std::forward_iterator_tag, Value>
{ {
public: public:
ConstIterator() ConstIterator(): _initialized(false)
{ {
} }
ConstIterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt): ConstIterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt):
_vecIt(vecIt), _vecIt(vecIt),
_endIt(endIt), _endIt(endIt),
_buckIt(buckIt) _buckIt(buckIt),
_initialized(true)
{ {
} }
ConstIterator(const ConstIterator& it): ConstIterator(const ConstIterator& it):
_vecIt(it._vecIt), _vecIt(it._vecIt),
_endIt(it._endIt), _endIt(it._endIt),
_buckIt(it._buckIt) _buckIt(it._buckIt),
_initialized(it._initialized)
{ {
} }
@ -120,9 +123,21 @@ public:
void swap(ConstIterator& it) void swap(ConstIterator& it)
{ {
using std::swap; using std::swap;
swap(_vecIt, it._vecIt); // uninitialized iterators crash when swapped
swap(_endIt, it._endIt); if (_initialized)
swap(_buckIt, it._buckIt); {
swap(_vecIt, it._vecIt);
swap(_endIt, it._endIt);
swap(_buckIt, it._buckIt);
swap(_initialized, it._initialized);
}
else
{
_vecIt = it._vecIt;
_endIt = it._endIt;
_buckIt = it._buckIt;
_initialized = it._initialized;
}
} }
bool operator == (const ConstIterator& it) const bool operator == (const ConstIterator& it) const
@ -170,6 +185,7 @@ public:
BucketVecIterator _vecIt; BucketVecIterator _vecIt;
BucketVecIterator _endIt; BucketVecIterator _endIt;
BucketIterator _buckIt; BucketIterator _buckIt;
bool _initialized;
friend class LinearHashTable; friend class LinearHashTable;
}; };
@ -194,7 +210,7 @@ public:
Iterator& operator = (const Iterator& it) Iterator& operator = (const Iterator& it)
{ {
Iterator tmp(it); Iterator tmp(it);
swap(tmp); ConstIterator::swap(tmp);
return *this; return *this;
} }

View File

@ -67,7 +67,7 @@ public:
TemporaryFile(); TemporaryFile();
/// Creates the TemporaryFile. /// Creates the TemporaryFile.
TemporaryFile(const std::string& tempDir); TemporaryFile(const std::string& tempDir);
/// Creates the TemporaryFile using the given directory. /// Creates the TemporaryFile using the given directory.
~TemporaryFile(); ~TemporaryFile();

View File

@ -155,7 +155,8 @@ void HashMapTest::testIterator()
} }
std::map<int, int> values; std::map<int, int> values;
IntMap::Iterator it = hm.begin(); IntMap::Iterator it; // do not initialize here to test proper behavior of uninitialized iterators
it = hm.begin();
while (it != hm.end()) while (it != hm.end())
{ {
assert (values.find(it->first) == values.end()); assert (values.find(it->first) == values.end());