user2835098 user2835098 - 4 months ago 21
Linux Question

Segmentation fault on linux (g++) but not on Mac OS.?

First of all I would like to apologize for my large code. I tried to keep it structured, but I am still new to programming in C++.

I created a C++ algorithm on OSX and it worked just fine. I need to run this program on Linux however. Compiling on Linux gave no errors, however when I run the program it gives the following error:

Segmentation fault (core dumped)


I am a newbie in debugging code and have tried to debug it with gdb, but I don't know how I should continue. The information gdb gives is the following:

c2f_function(new_candidates2, old_candidates, feature_list);
(gdb)

Program received signal SIGSEGV, Segmentation fault.
0x0000000000403dc5 in c2f_function (new_candidates=std::list = {...}, old_candidates=std::list = {...},
feature_list=empty std::list) at /home/martin/emc/group4/src/c2f_function.cpp:36
36 norm = iter_old->x -iter_new->x;


I have added the code below, it consists of a main file c2f.cpp, a header file c2f.hpp and an additional file where I store functions c2f_functions.cpp.

The error seems to happen when I pass 3 lists by reference to a function called c2f_functions. this function is within the c2f_functions.cpp script.

My questions are,


  1. how can I solve this?

  2. why does it work well under OSX but not under Linux?



Many thnaks!

MAIN FILE c2f.cpp:

#include "c2f.hpp"
#include "c2f_function.cpp"


int main()
{
// define variables
double x, y;

// create old candidates list
list<Candidate> old_candidates;

// create new candidates list
list<Candidate> new_candidates1;
list<Candidate> new_candidates2;
list<Candidate> new_candidates3;

// create new features list
list<Candidate> feature_list;

//=============================================================================//
// LOAD FIRST DATA SET
//-----------------------------------------------------------------------------//

ifstream file1_("newcandidates_it0.txt");
if (file1_.is_open())
{
cout << "Reading file...1 " << endl;
while( file1_ >> x >> y)
{
// cout << x << "," << y << endl;
new_candidates1.push_back(Candidate(x , y));

}
file1_.close();
}
else {cout << "file is not open";}
//=============================================================================//

c2f_function(new_candidates1, old_candidates, feature_list);


//=============================================================================//
// LOAD SECOND DATA SET
//-----------------------------------------------------------------------------//

ifstream file2_("newcandidates_it1.txt");
if (file2_.is_open())
{
cout << "Reading file...2 " << endl;
while( file2_ >> x >> y)
{
// cout << x << "," << y << endl;
new_candidates2.push_back(Candidate(x , y));

}
file2_.close();
}
else {cout << "file is not open";}
//=============================================================================//

c2f_function(new_candidates2, old_candidates, feature_list);


HEADER FILE c2f.hpp

# include <iostream>
# include <stdlib.h>
# include <string>
# include <math.h>
# include <Eigen/Dense>
# include <cstdio>
# include <cstdlib>
# include <list>
# include <fstream>
# include <algorithm>
// # include <cstdarg>

using namespace std;
using namespace Eigen;

// correspondence margin: new point must lie w/i 10cm from old point
# define CORR_MARGIN 0.1
# define PERSIST_UB 3
# define PERSIST_LB -PERSIST_UB

class Candidate
{
public:
int id;
double x;
double y;
int persistency = 0;
int pflag = 0; // persistency flag

Candidate ( double xNew, double yNew ): x(xNew), y(yNew){}

void increasePersistency()
{
if (persistency < PERSIST_UB) // bound persistency from above
persistency++;
}
void decreasePersistency()
{
if (persistency > PERSIST_LB) // bound persistency from below
persistency--;
}
// bool operator< (const Candidate& right) const { return id < right.id; }

};

bool ascendingId ( Candidate a, Candidate b)
{
return a.id < b.id;
}

bool descendingId ( Candidate a, Candidate b)
{
return a.id > b.id;
}

bool ascendingPersistency ( Candidate a, Candidate b)
{
return a.persistency < b.persistency;
}

bool descendingPersistency ( Candidate a, Candidate b)
{
return a.persistency > b.persistency;
}

bool ascendingPflag ( Candidate a, Candidate b)
{
return a.pflag < b.pflag;
}

bool descendingPflag ( Candidate a, Candidate b)
{
return a.pflag > b.pflag;
}

bool sameId_Feature (Feature first, Feature second)
{ return first.id == second.id; }

bool samePflag (Candidate first, Candidate second)
{ return first.persistency == second.persistency; }


bool finder (Candidate first, Candidate second)
{return first.id == second.id;}


bool not_persistent (Candidate &a)
{ return (a.persistency==PERSIST_LB); }


Functions File c2f_function.cpp

void print_list(list<Candidate> &list2print)
{
for (auto const &iter : list2print)
{
cout << iter.x
<< "," << iter.y
<< " with id "
<< iter.id
<< " and persistency "
<< iter.persistency
<< endl;
}
}


void c2f_function(list<Candidate> &new_candidates, list<Candidate> &old_candidates, list<Candidate> &feature_list)
{

double norm;

//=============================================================================//
// CHECK FOR CORRESPONDENCE
//-----------------------------------------------------------------------------//

// Check if old candidates exist (initialization purposes)
if (old_candidates.empty() == 0) // old candidates exist
{
// Check Correspondence
for (auto iter_old = old_candidates.begin(); iter_old != old_candidates.end(); iter_old++)
{
// int persistency_upd_flag = 0;
for (auto iter_new = new_candidates.begin(); iter_new != new_candidates.end(); iter_new++)
{
// compute the norm between old_candidates and new_candidates
// norm = sqrt( pow(iter_old->x - iter_new->x, 2.0) + pow(iter_old->y - iter_new->y, 2.0));
norm = iter_old->x -iter_new->x;
if (norm <= CORR_MARGIN)
{
// Update position of old entry and increase persistency
iter_old -> x = iter_new->x;
iter_old -> y = iter_new->y;
iter_old -> increasePersistency();
// flag an update;
iter_old -> pflag = 1;

// remove list entry that has been coupled
new_candidates.erase(iter_new);
}
}
}
}
else
{
back_insert_iterator<list<Candidate>> it(old_candidates);

for (auto const &iter : new_candidates)
{
it = iter;
}
int counter=1;
for (auto iter = old_candidates.begin(); iter!= old_candidates.end(); iter++)
{
iter -> id = counter;

++counter;
}
cout << "initializing data set" << endl;
cout << endl << "====================================================" << endl;
return;
}
//=============================================================================//


//=============================================================================//
// DECREASE PERSISTENCY FOR NON-VIEWED CANDIDATES
//-----------------------------------------------------------------------------//

// remove persistency to non-associated candidates
old_candidates.sort(ascendingPflag);
for (auto iter = old_candidates.begin(); iter!= old_candidates.end(); iter++)
{
if ( iter -> pflag == 0 )
{
iter -> decreasePersistency();

find_if (feature_list.begin(), feature_list.end(),
[iter] (Candidate &item)
{
if (item.id == iter->id)
{
item.persistency = iter->persistency;
return true;
}
else return false;
}
);
}
// reset pflags
iter -> pflag = 0;
}
//=============================================================================//


//=============================================================================//
// ADD id TO REMAINING new_candidates LIST
//-----------------------------------------------------------------------------//

// get new id
old_candidates.sort(descendingId);
int new_id = old_candidates.begin() -> id + 1;

// add id to added items to old_candidates
for (auto iter = new_candidates.begin(); iter!= new_candidates.end(); iter++)
{
iter -> id = new_id;
new_id++;
}
//=============================================================================//

//=============================================================================//
// MERGE REMAINING new_candidates WITH old_candidates LIST
//-----------------------------------------------------------------------------//
old_candidates.splice(old_candidates.end(), new_candidates);
//=============================================================================//


//=============================================================================//
// ADD TO feature_list
// REMOVE FROM feature_list
// REMOVE FROM old_list
//-----------------------------------------------------------------------------//

// removing from old_candidates when persistency @ lower bound
old_candidates.sort(ascendingPersistency);

for (auto const &iter_old : old_candidates)
{

if (iter_old.persistency == PERSIST_LB)
{
old_candidates.pop_front();
}
else
{break;}
}

// removing from feature_list when persistency @ lower bound
feature_list.sort(ascendingPersistency);

for (auto const &iter_feat : feature_list)
{
if (iter_feat.persistency == PERSIST_LB)
{
feature_list.pop_front();
}
else
{break;}
}


// sorting
old_candidates.sort(descendingPersistency);

// adding
back_insert_iterator<list<Candidate>> it(feature_list);

// define counter
int counter;

for (auto const &iter_old : old_candidates)
{
counter =0;
if (iter_old.persistency == PERSIST_UB)
{
if (feature_list.size()>0)
{
for (auto iter_feat = feature_list.begin(); iter_feat != feature_list.end(); iter_feat++)
{
if (iter_feat->id == iter_old.id)
{
iter_feat->x = iter_old.x;
iter_feat->y = iter_old.y;
iter_feat->persistency = iter_old.persistency;
counter = 0;
break;
}
else
{
counter++;
}
}
if (counter >0)
{
it = iter_old;
}

}
else
it = iter_old;
}
else
{
break;
}

}

//=============================================================================//


//=============================================================================//
// DISPLAY FEATURE LIST
//-----------------------------------------------------------------------------//
if (feature_list.size() > 0)
{
feature_list.sort(ascendingId);
cout << "Feature members" << endl;
print_list(feature_list);
cout << endl << "====================================================" << endl;
}
else
cout << endl << "====================================================" << endl;
//=============================================================================//

}

//*****************************************************************************//
//*****************************************************************************//

Answer

I'm not sure but I suspect the problem is that you erase an iterator and, next, you use (increment) it.

The following is the crucial part

  for (auto iter_new = new_candidates.begin(); iter_new != new_candidates.end(); iter_new++)
  {
    norm = iter_old->x -iter_new->x;
    if (norm <= CORR_MARGIN)
    {
      // [...]
      new_candidates.erase(iter_new);
    }
  }

When you erase(iter_new), iter_new become an iterator pointing to an invalid object; incrementing it (iter_new++) give you (if I'm not wrong) an undefined value and the following iter_new->x can segmentation fault your program.

I suppose that a solution can be the use of the postfix increment calling erase() so that erase() call a copy of iter_new and iter_new is incremented to a valid iterator before the call to erase(); something like

  auto = new_candidates.begin();
  while ( iter_new != new_candidates.end() )
  {
    norm = iter_old->x -iter_new->x;
    if (norm <= CORR_MARGIN)
    {
      // [...]
      new_candidates.erase( iter_new++ );
    }
    else
      ++iter_new;
  }

p.s.: sorry for my bad English