C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Segmentation fault with STL list class - PLEASE HELP

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
cpptutor2000@yahoo.com
Guest





PostPosted: Fri Jul 22, 2005 8:40 pm    Post subject: Segmentation fault with STL list class - PLEASE HELP Reply with quote



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





PostPosted: Fri Jul 22, 2005 9:36 pm    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote



[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





PostPosted: Mon Jul 25, 2005 10:30 am    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote





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





PostPosted: Mon Jul 25, 2005 11:00 am    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote

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





PostPosted: Mon Jul 25, 2005 11:02 am    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with 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 );

Back to top
Earl Purple
Guest





PostPosted: Mon Jul 25, 2005 11:23 am    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote

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





PostPosted: Mon Jul 25, 2005 6:52 pm    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote

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





PostPosted: Mon Jul 25, 2005 7:01 pm    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote

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





PostPosted: Wed Jul 27, 2005 7:13 pm    Post subject: Re: Segmentation fault with STL list class - PLEASE HELP Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.