 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
cpptutor2000@yahoo.com Guest
|
Posted: Fri Jul 22, 2005 8:40 pm Post subject: Segmentation fault with STL list class - PLEASE HELP |
|
|
I am using an STL list to store data packets in a network simulator.
The data packets are really C structs, which have other C structs
inside them. These structs contain
unsigned char arrays of various sizes, and some unsigned int values.
There are no pointers values stored in these structs.
I have a function, from inside of which I have a loop as follows:
Please note that dataPacketStore is the name of the struct being
stored.
if(!dlist.empty()){
list<dataPacketStore>::iterator iter;
list<dataPacketStore>::iterator dbegin = dlist.begin();
list<dataPacketStore>::iterator dend = dlist.end();
for(iter = dbegin; iter != dend; iter++)
if((*iter).disabled == true) dlist.erase(iter);
//'disabled' is a boolean variable in the struct dataPacketStore
}
Calling this erase method causes a segmentation fault. Is this because
of the fact that nested structs are there? Any help or suggestions
would be greatly appreciated.
Thanks in advance for your help.
|
|
| Back to top |
|
 |
Thomas Tutone Guest
|
Posted: Fri Jul 22, 2005 9:36 pm Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
[email]cpptutor2000 (AT) yahoo (DOT) com[/email] wrote:
| Quote: | I am using an STL list to store data packets in a network simulator.
|
[snip]
| Quote: | I have a function, from inside of which I have a loop as follows:
Please note that dataPacketStore is the name of the struct being
stored.
if(!dlist.empty()){
list<dataPacketStore>::iterator iter;
list<dataPacketStore>::iterator dbegin = dlist.begin();
list<dataPacketStore>::iterator dend = dlist.end();
for(iter = dbegin; iter != dend; iter++)
if((*iter).disabled == true) dlist.erase(iter);
|
Calling list's erase member function invalidates all iterators that
point to the value that was removed. So, in your example, you erase
the element pointed to by iter, which invalidates iter (think about it
- it points to an element that has been removed from the list). Then
you try to increment iter. That leads to undefined behavior (which can
include seg faults). But erase actually returns a valid iterator. Try
this instead (untested):
if (iter->disabled) iter = dlist.erase(iter);
Best regards,
Tom
|
|
| Back to top |
|
 |
Greg Guest
|
Posted: Mon Jul 25, 2005 10:30 am Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
Thomas Tutone wrote:
| Quote: | cpptutor2000 (AT) yahoo (DOT) com wrote:
I am using an STL list to store data packets in a network simulator.
[snip]
I have a function, from inside of which I have a loop as follows:
Please note that dataPacketStore is the name of the struct being
stored.
if(!dlist.empty()){
list<dataPacketStore>::iterator iter;
list<dataPacketStore>::iterator dbegin = dlist.begin();
list<dataPacketStore>::iterator dend = dlist.end();
for(iter = dbegin; iter != dend; iter++)
if((*iter).disabled == true) dlist.erase(iter);
Calling list's erase member function invalidates all iterators that
point to the value that was removed. So, in your example, you erase
the element pointed to by iter, which invalidates iter (think about it
- it points to an element that has been removed from the list). Then
you try to increment iter. That leads to undefined behavior (which can
include seg faults). But erase actually returns a valid iterator. Try
this instead (untested):
if (iter->disabled) iter = dlist.erase(iter);
Best regards,
Tom
|
Your suggestion will fix the crash, but it has introduced another, more
subtle problem.
The loop will now skip over the iterator that erase() returned, by
incrementing it before the test is next evaluated. For every item
deleted (unless it's the last in the list) another item in the list
will be skipped.
Greg
|
|
| Back to top |
|
 |
Earl Purple Guest
|
Posted: Mon Jul 25, 2005 11:00 am Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
which is why you should probably prefer to use the algorithmic
dlist.erase( std::remove_if( dbegin, dend, isDisabled ) );
where isDisabled is defined as:
bool isDisabled ( const dataPacketStore & dps )
{
return dps.disabled;
}
and possibly you could use a function object:
struct IsDisabled
{
bool operator() ( const dataPacketStore & dps ) const
{
return dps.disabled;
}
};
in which case change the algorithmic call to
dlist.erase( std::remove_if( dbegin, dend, IsDisabled() ) );
|
|
| Back to top |
|
 |
Earl Purple Guest
|
Posted: Mon Jul 25, 2005 11:02 am Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
oops too late I can't go back and retrieve my message. But you'll need
another dend in the erase thus:
dlist.erase( std::remove_if( dbegin, dend, isDisabled ), dend );
and
dlist.erase( std::remove_if( dbegin, dend, IsDisabled() ), dend );
|
|
| Back to top |
|
 |
Earl Purple Guest
|
Posted: Mon Jul 25, 2005 11:23 am Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
actually no need for that at all as list has its own remove_if function
thus:
dlist.remove_if( dbegin, dend, isDisabled );
or
dlist.remove_if( dbegin, dend, IsDisabled() );
The other method will work but using list's own remove_if is preferred.
|
|
| Back to top |
|
 |
Clark S. Cox III Guest
|
Posted: Mon Jul 25, 2005 6:52 pm Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
On 2005-07-25 07:02:06 -0400, "Earl Purple" <earlpurple0 (AT) yahoo (DOT) com> said:
| Quote: | oops too late I can't go back and retrieve my message. But you'll need
another dend in the erase thus:
dlist.erase( std::remove_if( dbegin, dend, isDisabled ), dend );
and
dlist.erase( std::remove_if( dbegin, dend, IsDisabled() ), dend );
|
Or just:
dlist.remove_if(isDisabled)
and
dlist.remove_if(IsDisabled());
--
Clark S. Cox, III
[email]clarkcox3 (AT) gmail (DOT) com[/email]
|
|
| Back to top |
|
 |
Thomas Tutone Guest
|
Posted: Mon Jul 25, 2005 7:01 pm Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
Greg wrote:
| Quote: | Calling list's erase member function invalidates all iterators that
point to the value that was removed. So, in your example, you erase
the element pointed to by iter, which invalidates iter (think about it
- it points to an element that has been removed from the list). Then
you try to increment iter. That leads to undefined behavior (which can
include seg faults). But erase actually returns a valid iterator. Try
this instead (untested):
if (iter->disabled) iter = dlist.erase(iter);
Your suggestion will fix the crash, but it has introduced another, more
subtle problem.
The loop will now skip over the iterator that erase() returned, by
incrementing it before the test is next evaluated. For every item
deleted (unless it's the last in the list) another item in the list
will be skipped.
|
Absolutely right. Thanks for the correction.
I suppose that one could do something like:
while (iter!=dlist.end() && iter->disabled) iter = dlist.erase(iter);
But I agree with another poster's suggestion that one is better off
using an algorithm-like member function instead.
Best regards,
Tom
|
|
| Back to top |
|
 |
Clark S. Cox III Guest
|
Posted: Wed Jul 27, 2005 7:13 pm Post subject: Re: Segmentation fault with STL list class - PLEASE HELP |
|
|
On 2005-07-25 15:01:09 -0400, "Thomas Tutone" <Thomas8675309 (AT) yahoo (DOT) com> said:
| Quote: | Greg wrote:
Calling list's erase member function invalidates all iterators that
point to the value that was removed. So, in your example, you erase
the element pointed to by iter, which invalidates iter (think about it
- it points to an element that has been removed from the list). Then
you try to increment iter. That leads to undefined behavior (which can
include seg faults). But erase actually returns a valid iterator. Try
this instead (untested):
if (iter->disabled) iter = dlist.erase(iter);
Your suggestion will fix the crash, but it has introduced another, more
subtle problem.
The loop will now skip over the iterator that erase() returned, by
incrementing it before the test is next evaluated. For every item
deleted (unless it's the last in the list) another item in the list
will be skipped.
Absolutely right. Thanks for the correction.
I suppose that one could do something like:
while (iter!=dlist.end() && iter->disabled) iter = dlist.erase(iter);
|
This, of course, would stop at the first enabled object:
(D=Disabled, E=Enabled)
Before: (DDDDEDED)
After: (EDED)
| Quote: |
But I agree with another poster's suggestion that one is better off
using an algorithm-like member function instead.
|
--
Clark S. Cox, III
[email]clarkcox3 (AT) gmail (DOT) com[/email]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|