Re: Problem with Vectors and STL/ATL in Visual C++ 2005
Colin J Paterson wrote:
iNumElements = m_Tables.GetSize();
m_Tables.GetAddress(iNumElements), NULL, AtlFlagNoCopy);
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.
Okay, then you know for the future what to document there. Anyhow, comparing
if(IsEmpty() || (iIndex < 0) || iIndex > m_vector.size())
if( iIndex < m_vector.size())
The above variant is definitively broken C++ code. Nothing about external
requirements will ever change that. I repeat, you must not call vector's
operator with a value equal to or greater than its size. Period, no
Now, for the enumerator's Init(), you still need two pointers that represent
the start and past-the-end of the sequence. If the sequence is empty, you
could return NULL or some other dummy value for index=0 and index=size.
Otherwise, you could return the address of the first element
(vector::front()) plus the index. I would consider creating a get_range()
function instead, because the habit of letting a one-off index slip through
is really bad and confusing. At the very least, it deserves being
I stress, this worked fine in VC6
Let me repeat what I wrote:
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.
Just for completeness, there are two additional alternatives you could use:
1. Move the computation of the past-the-end pointer to outside the array
This doesn't cater for an empty container though, but I think that's an
error all along, which might deserve special handling anyway.
2. Always maintain an additional object in the array. You would then insert
new elements before that last element instead of using push_back() etc, but
you would have the guarantee that the contained array is never empty and
that the past-the-end element exists and is accessible. You would have to
adjust methods that use the size of the vector accordingly.