Re: Problem with Vectors and STL/ATL in Visual C++ 2005
The code is used in the _NewEnum function as follows
STDMETHODIMP CmxTables::get__NewEnum(LPUNKNOWN *pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
EnumVar *pEnumerator;
long iNumElements;
pEnumerator = new EnumVar;
iNumElements = m_Tables.GetSize();
pEnumerator->Init(m_Tables.GetAddress(0), m_Tables.GetAddress(iNumElements),
NULL, AtlFlagNoCopy);
if (FAILED(pEnumerator->QueryInterface(IID_IUnknown, (void**)pVal)))
goto cleanup;
return S_OK;
cleanup:
return E_INVALIDARG;
}
If I make the changes you say I get a Automation Error in Visual Basic when
it returns the empty variant. The get address function seems to deliberately
return past the the end of the vector as described in the MSDN for
CComEnumImpl::Init.
Here is the function (m_bReverse is always false).
VARIANT* CmxArray::GetAddress(long iIndex)
{
// deliberate index error here
if(!m_bReverse)
{
if(IsEmpty() || (iIndex < 0) || iIndex >= m_vector.size())
{
m_emptyVariant.vt = VT_I2;
m_emptyVariant.iVal = -1;
return &m_emptyVariant;
}
return &m_vector[iIndex].m_Variant;
}
else
{
if (IsEmpty() || (iIndex < 0) || iIndex >= m_deque.size())
{
m_emptyVariant.vt = VT_I2;
m_emptyVariant.iVal = -1;
return &m_emptyVariant;
}
return &m_deque[iIndex].m_Variant;
}
}
I stress, this worked fine in VC6 and if I make a change to get__NewEnum to
look for (iNumElements - 1) then I lose the last element from every
vector????
"Ulrich Eckhardt" <eckhardt@satorlaser.com> wrote in message
news:jibji3-fcu.ln1@satorlaser.homedns.org...
Colin J Paterson wrote:
if(IsEmpty() || (iIndex < 0) || iIndex > m_vector.size())
{
return &m_emptyVariant;
}
return &m_vector[iIndex].m_Variant;
This code is bogus. Firstly, iIndex usually is a size_t which means it is
unsigned, therefore no need to check if it is less than zero. Secondly,
you
check if the index is in the range of valid indices for the vector and
additionally you check if the vector is empty (at least that's what I
think
you do, can't tell without all the code) which is redundant. Thirdly, the
maximum valid index you may dereference in a vector is its size minus
one -
you only check for it being greater than the size though. How did this get
past your unittests, I wonder?
So, the implementation then simply becomes this:
if( iIndex < m_vector.size())
return &m_vector[iIndex].m_Variant;
return &m_emptyVariant;
I didn't write the code and I'm not sure why there is a deliberate
indexing error here pointing to an element that doesn't exist.
Okay, that means that someone f***ed up big time by not documenting the
whys
of code appropriately. Time to refactor.
This seems to work in Visual C++ 6 but in 2005 it throws a subscript
out of range error? Any ideas why?
Simply because its standardlibrary is better, in debug mode it features a
checked implementation like STLport that catches several errors where the
standard just shrugs and says "undefined behaviour, no diagnostic
required". The code was broken all along though.
Uli