Reputation: 15
The following function I made is causing an error "Aborted(core dumped)" when I try to run my program in cygwin. I tried using gdb and I get:
"Program received signal SIGABRT, Aborted. 0x00000000 in ?? ()"
I have tried erasing thee first and then me, but this generates the same result, a crash during the second erase (in that case erase(me)).
The basic idea of the CoalesceOverlaps function is to combine OVERLAPs that themselves overlap, so I sort the list, check two adjacent (me & thee) elements for overlap and if they do overlap, create a new element that is the combination of me & thee, delete me & thee and replace them with the new element that is the combination.
The function works logically as I tested it with a hard coded list of a hand full of elements and the output was coalesced correctly, but when I tried to implement it in my real program that has large lists/empty lists etc, it fails.
EDIT(from cnvr_check_v1.1.exe.stackdump):
Stack trace:
Frame Function Args
0028A624 76E31194 (000000E8, 0000EA60, 00000000, 0028A758)
0028A638 76E31148 (000000E8, 0000EA60, 000000A4, 0028A734)
0028A758 610DC559 (00000001, 80038390, 0000001D, 610EBCCC)
0028A848 610D9913 (00000000, 0028A890, 0028A878, 61187784)
0028A8A8 610D9DEE (0028FF14, 00000001, 0028A8E8, 00000006)
0028A958 610D9F40 (00000158, 00000006, 0053002B, 61187784)
0028A978 610D9F6C (00000006, 00000006, 0028A9A8, 610B66D1)
0028A9A8 610DA233 (00000000, 0028A9DC, 0028A9C8, 610FD3CA)
End of stack trace
The code:
void CoalesceOverlaps(list<OVERLAP>& overlap_regions)
{
cout << "Begining of CoalesceOverlaps function\n";
overlap_regions.sort(OVERLAPStartSortPredicate);
//now coalesce
cout << "Didn't fail during sorting\n";
list<OVERLAP>::iterator me = overlap_regions.begin(),
end = overlap_regions.end();
if ( me != end ) // Treat empty list
for(list<OVERLAP>::iterator thee = ++me; // Post-increment
thee != end;
me++, thee++)
{
cout << "just before thee-> start less than... if\n";
//cout << me->stop << endl;
if(thee->start <= me->stop) //hit to coalesce them
{
cout << "thee->ID:" << thee->id << endl;
cout << "thee->start:" << thee->start << endl;
cout << "made it to the thee->start less than me->stop if\n";
long temp_start = min(thee->start,me->start),temp_stop = max(thee->stop,me->stop);
OVERLAP temp_region;
temp_region.start = temp_start;
temp_region.stop = temp_stop;
cout << "just before the first erase\n";
//overlap_regions.push_front(temp_region);
list<OVERLAP>::iterator temp_itr = overlap_regions.erase(me);
cout << "thee->ID:" << thee->id << endl;
cout << "thee->start:" << thee->start << endl;
cout << "just before the second erase\n";
//cout << thee->id;
overlap_regions.erase(thee);
cout << "past the erases\n";
overlap_regions.insert(temp_itr,temp_region);
}
cout << "bottom of the for\n";
}
cout << "End of CoalesceOverlaps function\n";
}
EDIT (corrected function below) Thanks!:
void CoalesceOverlaps(list<OVERLAP>& overlap_regions)
{
overlap_regions.sort(OVERLAPStartSortPredicate);
//iterators for keeping track of the two nodes we are comparing
list<OVERLAP>::iterator me = overlap_regions.begin(),
thee = overlap_regions.begin(),
end = overlap_regions.end();
if ( me != end ) // Treat empty list
thee++; //sets it to the second element
if(thee!=end) //Treat list with one element
while(thee != end) //lets keep comparing until we right the end
{
if(thee->start <= me->stop) //hit to coalesce them
{
long temp_start = min(thee->start,me->start),temp_stop = max(thee->stop,me->stop);
OVERLAP temp_region;
temp_region.start = temp_start;
temp_region.stop = temp_stop;
overlap_regions.erase(me);
list<OVERLAP>::iterator temp_itr = overlap_regions.erase(thee);
me = overlap_regions.insert(temp_itr,temp_region);
thee = temp_itr;
}
else{
me++;
thee++;
}
}
}
Upvotes: 1
Views: 2071
Reputation: 66244
I believe your me
erasure is invalidating your thee
iterator.
for(list<OVERLAP>::iterator thee = ++me; // Post-increment
This guarantees they're the same node in your for-initializer. You're comment says post-increment. that is not post-increment. Thus you then do this:
list<OVERLAP>::iterator temp_itr = overlap_regions.erase(me);
Followed immediately by this:
cout << "thee->ID:" << thee->id << endl;
cout << "thee->start:" << thee->start << endl;
...etc. After the erase of 'me', thee
is no longer valid. Accessing it for read is undefined behavior, but will probably work because there is still something at the referenced data pointer. But it is none-the-less undefined behavior that is finally manifesting itself with the erase()
call.
Upvotes: 2