views:

523

answers:

5

I created a program, and it uses the vector.h #include, and iterators, etc... But when I run the program, under certain circumstances (I'm still trying to figure out what those would be) I get an assertion error refering me to line 98 of vector.h. I went to line 98 of vector.h and got this:

 #if _HAS_ITERATOR_DEBUGGING
     if (this->_Mycont == 0
      || _Myptr < ((_Myvec *)this->_Mycont)->_Myfirst
      || ((_Myvec *)this->_Mycont)->_Mylast <= _Myptr)
      {
      _DEBUG_ERROR("vector iterator not dereferencable");
      _SCL_SECURE_OUT_OF_RANGE;
      }

Can somebody please tell me what this means and what in my program is causing this assertion?

NB: Line 98, for the record, is the one that begins "_DEBUG_ERROR("vect..."

NB: This is the code in my program that I BELIEVE triggered the error, I'm not entirely sure, though.

CODE:

for(aI = antiviral_data.begin(); aI < antiviral_data.end();)
    {
     for(vI = viral_data.begin(); vI < viral_data.end();)
     {
      if((*aI)->x == (*vI)->x && (*aI)->y == (*vI)->y)
      {
       vI = viral_data.erase(vI);
       aI = antiviral_data.erase(aI);
      }
      else
      {
       vI++;
      }
     }
     if((*aI)->x >= maxx || (*aI)->x < 0 || (*aI)->y >= maxy || (*aI)->y < 0)
     {
      aI = antiviral_data.erase(aI);
     }
     else
     {
      aI++;
     }
    }
+10  A: 

The runtime is detecting that you are dereferencing an iterator that is before begin() or after end().

Imagine if you delete the last item in the antiviral_data vector in line 7:

aI = antiviral_data.erase(aI);

aI gets set to antiviral_data.end(), and when you dereference it in line 14:

if((*aI)->x >= maxx ...

and also in line 5:

if((*aI)->x == (*vI)->x

You are dereferencing an out of bounds iterator.

The fix is to check that aI != antiviral_data.end() after the erase call to make sure you haven't hit the end of the vector before you continue on using it.

Eclipse
+6  A: 

You really want to look at STL algorithms like remove_if instead of doing this stuff manually.

Nikolai N Fetissov
+4  A: 

A small general comment: When checking an iterator for end(), do not use "<" but only "!=". So, the first lines of your code should look like:

for(aI = antiviral_data.begin(); aI != antiviral_data.end();)
{
  for(vI = viral_data.begin(); vI != viral_data.end();)
  {
    ...

However, as Josh already pointed, your specific bug is in line 7.

beef2k
May I ask why I should use "!="?
Keand64
The "less than" operator is not defined for all iterators - see this overview: http://cplusplus.com/reference/std/iterator . As you can see, the inequality operators exists for all iterators. Furthermore, the "less than" operator might be much slower (it might be of linear complexity) compared to the inequality operator (which is constant).And in your case, there is no need to check if your iterator `aI` is smaller at the end, but only that you haven't reached the end yet.
beef2k
A: 

erasing an element in a vector invalidates all iterators.

The iterator returned from erase is always valid (or at least equal to end())
Zan Lynx
+1  A: 

In addition to the accepted answer, and to elaborate on slavy13's answer -
(EDIT - and as mentioned by Josh, not directly relevant to this question - I'm leaving it here for reference).

Code (but not this code) sometimes assumes that you can remove elements from a vector, and keep iterating. This is a false assumption - once you remove an element from a vector, all other iterators following the removed element are invalidated - you can no longer assume they are correct, and "bad things" can happen if you keep using them.

The reason for this is because a vector actually stores information in an array form. When an element is removed, all following elements are copied one cell down. The iterators aren't updated accordingly.

It is strongly recommended to consult STL documentation whenever trying to do such things, because it is entirely possible such code would work on a certain implementation of STL accidentally, but fail on others.

Hexagon