List Iterator Not Incrementable?

F

freckred76

Hi,

I think this might be a VC++ problem. I am using Microsoft Visual
Studio 2005 Full Version (8.0).

I have a simple for loop that iterates over a list using the standard
iterator. The list is populated with a struct _BLOCK defined as:

typedef struct
{
int iX ;
int iY ;
int iFrame ;
double dIntensity ;
} _BLOCK ;

std::list<_BLOCK> list_block;
std::list<_BLOCK>::iterator list_block_it;

for (list_block_it = list_block.begin (); list_block_it !=
list_block.end (); list_block_it++)
{
list_block_it->dIntensity -= 0.025 ;
if (list_block_it->dIntensity < 0.0)
{ // Delete this item
list_block_it = list_block.erase (list_block_it);
}
}

The code seems fine to me, but it always fails an assert at run-time,
claiming "list iterator not incrementable." I haven't been able to
find any documentation or threads about this problem. Also, it seems
like this code runs fine when built with g++ or previous versions of
VC++.

Any help is greatly appreciated,

Nate
 
A

Andre Kostur

(e-mail address removed) wrote in @o13g2000cwo.googlegroups.com:
Hi,

I think this might be a VC++ problem. I am using Microsoft Visual
Studio 2005 Full Version (8.0).

I have a simple for loop that iterates over a list using the standard
iterator. The list is populated with a struct _BLOCK defined as:

typedef struct
{
int iX ;
int iY ;
int iFrame ;
double dIntensity ;
} _BLOCK ;

std::list<_BLOCK> list_block;
std::list<_BLOCK>::iterator list_block_it;

for (list_block_it = list_block.begin (); list_block_it !=
list_block.end (); list_block_it++)
{
list_block_it->dIntensity -= 0.025 ;
if (list_block_it->dIntensity < 0.0)
{ // Delete this item
list_block_it = list_block.erase (list_block_it);

And... kaboom (well, Undefined Behaviour). If you happen to be erasing
the last element in your list, you'll increment it again for the for
loop... thus you inadvertantly end up attemtping to iterate past the .end
() iterator. BTW: it's possibly that you're compiling with a "debug-
mode" standard library which is checking for things like attempting to
increment past the end of a container.
 
?

=?iso-8859-1?Q?Ali_=C7ehreli?=

I have a simple for loop that iterates over a list using the standard
iterator. The list is populated with a struct _BLOCK defined as:

typedef struct
{
int iX ;
int iY ;
int iFrame ;
double dIntensity ;
} _BLOCK ;

std::list<_BLOCK> list_block;
std::list<_BLOCK>::iterator list_block_it;

for (list_block_it = list_block.begin (); list_block_it !=
list_block.end (); list_block_it++)
{
list_block_it->dIntensity -= 0.025 ;
if (list_block_it->dIntensity < 0.0)
{ // Delete this item
list_block_it = list_block.erase (list_block_it);

What if list_block_it becomes equal to list_block.end() at that point? It
could happen if erase erases the last item in the list.

Then, operator++ would be applied to an invalid iterator.
}
}

The code seems fine to me, but it always fails an assert at run-time,
claiming "list iterator not incrementable."

Your library is being very good to you :)
I haven't been able to
find any documentation or threads about this problem. Also, it seems
like this code runs fine when built with g++ or previous versions of
VC++.

Since it's undefined behavior, you are being unlucky on those platforms
because it "runs fine" on those platforms.

Ali
 
F

freckred76

Ali,

Yes, it may be undefined behavior, but it did work before, whereas now
it does not. You were right about the source of the error. I modified
the code to fix it. Thanks for your help! Sometimes you just don't
notice the simple stuff.

Nate
 
R

red floyd

Hi,

I think this might be a VC++ problem. I am using Microsoft Visual
Studio 2005 Full Version (8.0).

I have a simple for loop that iterates over a list using the standard
iterator. The list is populated with a struct _BLOCK defined as:

typedef struct
{
int iX ;
int iY ;
int iFrame ;
double dIntensity ;
} _BLOCK ;

std::list<_BLOCK> list_block;
std::list<_BLOCK>::iterator list_block_it;

for (list_block_it = list_block.begin (); list_block_it !=
list_block.end (); list_block_it++)
{
list_block_it->dIntensity -= 0.025 ;
if (list_block_it->dIntensity < 0.0)
{ // Delete this item
list_block_it = list_block.erase (list_block_it);
}
}

Ali and Andre have already suggested the answer to your problem. I'd
like to address something else.

1. Your typedef is unnecessary, You should define it as "struct BLOCK"
(note the lack of an underscore), which brigns me to...
2. The identifier _BLOCK is reserved. Any identifier with a leading
underscore followed by a capital letter is reserved to the implementation.
 
F

freckred76

red floyd,

I must admit that I did not write this code. I simply tried compiling
it for a friend under 2003, which worked, and 2005, which did not work.
I could not see a problem, when of course the problem was very
obvious. However, let's not pick it to pieces, shall we?

nate
 
B

Ben Pope

red floyd,

I must admit that I did not write this code. I simply tried compiling
it for a friend under 2003, which worked, and 2005, which did not work.
I could not see a problem, when of course the problem was very
obvious. However, let's not pick it to pieces, shall we?

It's sometimes difficult to accept criticism, and if you post code to
this group it WILL be criticised heavily, but then, that's what you're
asking for. Learn from the criticism, don't take it personally.

Ben Pope
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Hi,

I think this might be a VC++ problem. I am using Microsoft Visual
Studio 2005 Full Version (8.0).

I have a simple for loop that iterates over a list using the standard
iterator. The list is populated with a struct _BLOCK defined as:

typedef struct
{
int iX ;
int iY ;
int iFrame ;
double dIntensity ;
} _BLOCK ;

std::list<_BLOCK> list_block;
std::list<_BLOCK>::iterator list_block_it;

for (list_block_it = list_block.begin (); list_block_it !=
list_block.end (); list_block_it++)
{
list_block_it->dIntensity -= 0.025 ;
if (list_block_it->dIntensity < 0.0)
{ // Delete this item
Rather than this obvious comment ...
.... I'd expect a rationale why the next element in the list is not
tested.
list_block_it = list_block.erase (list_block_it);
}
}

The code seems fine to me, but it always fails an assert at run-time,
claiming "list iterator not incrementable." I haven't been able to
find any documentation or threads about this problem. Also, it seems
like this code runs fine when built with g++ or previous versions of
VC++.

Any help is greatly appreciated,

Nate

The correct way to remove element from a sequence is:
typedef std::list<int> List; // just a short-hand
typedef List::iterator Iter; // just a short-hand

List list;
for (Iter i = list.begin(); i != list.end();) {
if (*i < 0) i = list.erase(i);
else ++i;
}

Regards, Stephan
 
M

Michiel.Salters

red floyd,

I must admit that I did not write this code. I simply tried compiling
it for a friend under 2003, which worked, and 2005, which did not work.

The VC2005 compiler is improved (duh). It catches many errors
immediately
whereas with the VC2003 compiler you would have other problems later
on.
From experience, we prefer the VC2005 behavior. You can catch it before
the boss is looking ;)

Michiel.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top