GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 02-Mar-2008, 16:28
Algar Algar is offline
Junior Member
 
Join Date: Sep 2007
Posts: 92
Algar will become famous soon enough

STL <list> removing elements from inside FOR loop


I am getting a
debug assertion error:
Expression: list iterator not incremental


The list has 1 element and this error occurs at the line:
iter = pLoaded->timerCalls.erase(iter);

As I understand it, erase() is supposed to return the element after the one being erased, so this line SHOULD remove the single entry, and return list.end() I think. But obviously something is going wrong somewhere ?

CPP / C++ / C Code:
	//check the list of timer calls in current context
	list<TimerEntry>::iterator iter;
	for (iter = pLoaded->timerCalls.begin(); 
		 iter != pLoaded->timerCalls.end(); 
		 ++iter)
	{
		iter->time -= elapsed;	//subtrack elapsed time

		if (iter->time <= 0)	//if time is up
		{
			pLoaded->GLTimer(iter->value);			//call function with value

			iter = pLoaded->timerCalls.erase(iter);	//remove call from queue
		}
	}
  #2  
Old 02-Mar-2008, 17:47
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,648
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: STL <list> removing elements from inside FOR loop


Quote:
Originally Posted by Algar
I am getting a debug assertion error:
Expression: list iterator not incremental

If it removes the last element, then the iterator is pointing beyond the end of the list. The for statement increments it before going to the top of the loop. I don't think that this is illegal, but maybe your compiler doesn't like it.

Try the following:

CPP / C++ / C Code:
#include <iostream>
#include <list>

using namespace std;

int main()
{
    int iarray[] = {11, 22, 33, 44};
    list<int> intList(iarray, iarray + 4);

    list<int>::iterator iter;
    cout << "After initialization ";
    for (iter = intList.begin(); iter != intList.end(); ++iter) {
        cout << *iter << " ";
    }
    cout << endl << endl;

   for (iter = intList.begin(); iter != intList.end(); ++iter)
    {
        cout << "Top of loop: *iter = " << *iter << endl;
        iter = intList.erase(iter);
        cout << "Now the list size is  " << intList.size() << endl << endl;
        --iter; // for statement will increment it
    }
    return 0;
}

Here's my output (using GNU g++ on a LInux platform:
Code:
After initialization 11 22 33 44 Top of loop: *iter = 11 Now the list size is 3 Top of loop: *iter = 22 Now the list size is 2 Top of loop: *iter = 33 Now the list size is 1 Top of loop: *iter = 44 Now the list size is 0

Now comment out the --iter at the end of the loop. My compiler still doesn't complain, but notice the output:
Code:
After initialization 11 22 33 44 Top of loop: *iter = 11 Now the list size is 3 Top of loop: *iter = 33 Now the list size is 2

Bottom line: I don't know if this is the cause of your compiler's complaint or what, but I have a feeling your code leaves something to be desired.

Regards,

Dave
  #3  
Old 02-Mar-2008, 19:52
Algar Algar is offline
Junior Member
 
Join Date: Sep 2007
Posts: 92
Algar will become famous soon enough

Re: STL <list> removing elements from inside FOR loop


Subtle but important type correction in my first post:
incremental = incrementable

So I see the bug you meant, I was skipping ahead everytime I removed something since it would get incremented twice. Thanks.


Using your example:

With --iter
Debug Assertion Failure
Expression: list iterator not decrementable

Withought --iter
Same as your results.


New test results:
So I removed the .erase() call completely, and since I am (so far) just testing with 1 value in the list, I tried this method instead:

CPP / C++ / C Code:
	list<TimerEntry>::iterator iter;
	for (iter = pLoaded->timerCalls.begin(); 
		 iter != pLoaded->timerCalls.end(); 
		 ++iter)
	{
		iter->time -= elapsed;	//subtrack elapsed time

		if (iter->time <= 0)	//if time is up
		{
			pLoaded->GLTimer(iter->value);			//call function with value

			if (pLoaded->timerCalls.size() == 1)
				pLoaded->timerCalls.clear();
		
		}
	}

I am still getting
debug assertion error:
Expression: list iterator not incrementable

I don't really get it, it should never even TRY to increment the iterator in this case no ?
  #4  
Old 02-Mar-2008, 19:56
Algar Algar is offline
Junior Member
 
Join Date: Sep 2007
Posts: 92
Algar will become famous soon enough

Re: STL <list> removing elements from inside FOR loop


Actually, is list.End() supposed to be list.size()+1 ?
Maybe if I am doing clear() then size becomes 0, then the for loop tries to increment it again but now theres nothing in the list.

Arg, I dunno
  #5  
Old 02-Mar-2008, 20:05
Algar Algar is offline
Junior Member
 
Join Date: Sep 2007
Posts: 92
Algar will become famous soon enough

Re: STL <list> removing elements from inside FOR loop


Ok so, I got it wokring with a while loop instead

CPP / C++ / C Code:
	//check the list of timer calls in current context
	list<TimerEntry>::iterator iter = pLoaded->timerCalls.begin();

	while (iter != pLoaded->timerCalls.end())
	{
		iter->time -= elapsed;	//subtrack elapsed time

		if (iter->time <= 0)
		{
			pLoaded->GLTimer(iter->value);	//call function with value
			iter = pLoaded->timerCalls.erase(iter);
		}
		else
			++iter;
	}


If anyone is bored, and wants to explain the error of my previous ways, feel free, but don't feel you need to waste your time
  #6  
Old 03-Mar-2008, 08:27
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,648
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: STL <list> removing elements from inside FOR loop


Quote:
Originally Posted by Algar
...explain the error of my previous ways...

The fact is that my program had undefined behavior and just happened to work with that particular program and the particular compiler that I was using.

In my program after deleting the very first element, the iterator is still pointing to intList.begin(). Decrementing it at that point is a no-no, and the program with your compiler bails out. (In my case, decrementing it and then incrementing it resulted in apparently satisfactory behavior, but it's still wrong.)

Your solution is correct, and mine was incorrect.

I usually try compiling programs like this with different compilers before posting, but I didn't have access to a Windows platform at the time.

Another solution, in the same spirit as yours:

CPP / C++ / C Code:
#include <iostream>
#include <list>

using namespace std;

int main()
{
    int iarray[] = {-1, 22, -3, 44, -5};
    list<int> intList(iarray, iarray + 5);

    list<int>::iterator iter;
    cout << "After initialization ";
    for (iter = intList.begin(); iter != intList.end(); ++iter) {
        cout << *iter << " ";
    }
    cout << endl << endl;

    // the following is equivalent to your while loop
    for (iter = intList.begin(); iter != intList.end();) {
        cout << "Top of loop: *iter = " << *iter;
        if (*iter < 0) {
            cout << " <--- Erasing " << *iter;
            intList.erase(iter++); // Erase the current one and save the incremented iterator
        }
        else {
            ++iter;
        }
        cout << endl << "intList.size() = " << intList.size() << endl << endl;
    }
    return 0;
}

Output with various Windows and Linux/GNU compilers
Code:
After initialization 11 -2 33 -4 55 Top of loop: *iter = 11 List size = 5 Top of loop: *iter = -2 <--- erasing -2 List size = 4 Top of loop: *iter = 33 List size = 4 Top of loop: *iter = -4 <--- erasing -4 List size = 3 Top of loop: *iter = 55 List size = 3

Next-to-bottom line: it's OK to increment or decrement a valid iterator as long as the result is valid. Decrementing an iterator that whose value is begin() is not OK.

Bottom line: You can't prove a program is correct by testing alone.

I am glad you got to the bottom of things in spite of my error. Thanks for following up.


Regards,

Dave
  #7  
Old 03-Mar-2008, 10:01
Algar Algar is offline
Junior Member
 
Join Date: Sep 2007
Posts: 92
Algar will become famous soon enough

Re: STL <list> removing elements from inside FOR loop


Thanks for the assistance and the final clarification.
 
 

Recent GIDBlogWelcome to Baghdad by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
template comiling problems - need expert debugger! crq C++ Forum 1 01-Feb-2005 21:26

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 00:48.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.