C ++ segmentation when using erase in std :: list

I am trying to remove items from a C ++ linked list using erase and a list iterator:

 #include <iostream> #include <string> #include <list> class Item { public: Item() {} ~Item() {} }; typedef std::list<Item> list_item_t; int main(int argc, const char *argv[]) { // create a list and add items list_item_t newlist; for ( int i = 0 ; i < 10 ; ++i ) { Item temp; newlist.push_back(temp); std::cout << "added item #" << i << std::endl; } // delete some items int count = 0; list_item_t::iterator it; for ( it = newlist.begin(); count < 5 ; ++it ) { std::cout << "round #" << count << std::endl; newlist.erase( it ); ++count; } return 0; } 

I get this conclusion and cannot trace the reason:

 added item #0 added item #1 added item #2 added item #3 added item #4 added item #5 added item #6 added item #7 added item #8 added item #9 round #0 round #1 Segmentation fault 

I am probably mistaken, but I will still be grateful for the help. thanks.

+6
c ++ linked-list segmentation-fault erase
source share
4 answers

The main problem here is that you are using the value of iterator, it , after you erase on it. The erase method invalidates the iterator and therefore continues to use it, resulting in poor behavior. Instead, you want to use the erase return to get the next valid iterator after the value to be erased.

 it = newList.begin(); for (int i = 0; i < 5; i++) { it = newList.erase(it); } 

It also does not hinder to enable verification for newList.end() to take into account the case when there are at least 5 elements in the list .

 it = newList.begin(); for (int i = 0; i < 5 && it != newList.end(); i++) { it = newList.erase(it); } 

As Tim noted, here is a great link for erase

+20
source share

When you delete an element at position it , the iterator it becomes invalid - it points to the part of memory that you just freed.

The erase(it) function returns another iterator pointing to the next element in the list. Use it!

+3
source share

You invalidate your iterator with erase() in a loop. It would be easier to do something like this instead of your erase cycle:

 list_item_t::iterator endIter = newlist.begin(); std::advance(endIter, 5); newList.erase(newlist.begin(), endIter); 

You may also be interested in erase-remove idiom .

+2
source share

I'm doing it:

 for(list<type>::iterator i = list.begin(); i != list.end(); i++) { if(shouldErase) { i = list.erase(i); i--; } } 

Edited because I'm a boob who can't read, apparently, lol.

+2
source share

All Articles