diff --git a/include/wx/arrstr.h b/include/wx/arrstr.h index 5848679dad..d76a2859b4 100644 --- a/include/wx/arrstr.h +++ b/include/wx/arrstr.h @@ -364,7 +364,10 @@ protected: CompareFunction m_compareFunction; // set only from wxSortedArrayString private: - void Grow(size_t nIncrement = 0); // makes array bigger if needed + // Allocate the new buffer big enough to hold m_nCount + nIncrement items and + // return the pointer to the old buffer, which must be deleted by the caller + // (if the old buffer is big enough, just return NULL). + wxString *Grow(size_t nIncrement); size_t m_nSize, // current size of the array m_nCount; // current number of elements diff --git a/src/common/arrstr.cpp b/src/common/arrstr.cpp index 03441eef3e..94b64722ec 100644 --- a/src/common/arrstr.cpp +++ b/src/common/arrstr.cpp @@ -20,6 +20,7 @@ #endif #include "wx/arrstr.h" +#include "wx/scopedarray.h" #include "wx/beforestd.h" #include @@ -107,10 +108,14 @@ void wxArrayString::Copy(const wxArrayString& src) } // grow the array -void wxArrayString::Grow(size_t nIncrement) +wxString *wxArrayString::Grow(size_t nIncrement) { - // only do it if no more place - if ( (m_nSize - m_nCount) < nIncrement ) { + if ( (m_nSize - m_nCount) >= nIncrement ) + { + // We already have enough space. + return NULL; + } + // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would // be never resized! #if ARRAY_DEFAULT_INITIAL_SIZE == 0 @@ -123,6 +128,9 @@ void wxArrayString::Grow(size_t nIncrement) if (m_nSize < nIncrement) m_nSize = nIncrement; m_pItems = new wxString[m_nSize]; + + // Nothing to free, we hadn't had any memory before. + return NULL; } else { // otherwise when it's called for the first time, nIncrement would be 0 @@ -141,12 +149,12 @@ void wxArrayString::Grow(size_t nIncrement) for ( size_t j = 0; j < m_nCount; j++ ) pNew[j] = m_pItems[j]; - // delete old memory (but do not release the strings!) - delete [] m_pItems; + wxString* const pItemsOld = m_pItems; m_pItems = pNew; + + return pItemsOld; } - } } // deletes all the strings from the list @@ -289,7 +297,10 @@ size_t wxArrayString::Add(const wxString& str, size_t nInsert) return (size_t)lo; } else { - Grow(nInsert); + // Now that we must postpone freeing the old memory until we don't need it + // any more, i.e. don't reference "str" which could be a reference to one + // of our own strings. + wxScopedArray oldStrings(Grow(nInsert)); for (size_t i = 0; i < nInsert; i++) { @@ -309,7 +320,7 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert) wxCHECK_RET( m_nCount <= m_nCount + nInsert, wxT("array size overflow in wxArrayString::Insert") ); - Grow(nInsert); + wxScopedArray oldStrings(Grow(nInsert)); for (int j = m_nCount - nIndex - 1; j >= 0; j--) m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j]; @@ -328,7 +339,7 @@ wxArrayString::insert(iterator it, const_iterator first, const_iterator last) const int idx = it - begin(); // grow it once - Grow(last - first); + wxScopedArray oldStrings(Grow(last - first)); // reset "it" since it can change inside Grow() it = begin() + idx; diff --git a/tests/arrays/arrays.cpp b/tests/arrays/arrays.cpp index e768238bc8..badfb4e01e 100644 --- a/tests/arrays/arrays.cpp +++ b/tests/arrays/arrays.cpp @@ -346,6 +346,10 @@ void ArraysTestCase::wxStringArrayTest() a5.resize(3); CPPUNIT_ASSERT_EQUAL( 3, a5.size() ); CPPUNIT_ASSERT_EQUAL( "Foo", a5[2] ); + + wxArrayString a6; + a6.Add("Foo"); + a6.Insert(a6[0], 1, 100); } void ArraysTestCase::SortedArray()