Robert
Robert

Reputation: 15

Aborted (core dumped) C++ Cygwin

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

Answers (1)

WhozCraig
WhozCraig

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

Related Questions