linux (g++) 上的分段错误,但 Mac OS 上没有。?

Posted

技术标签:

【中文标题】linux (g++) 上的分段错误,但 Mac OS 上没有。?【英文标题】:Segmentation fault on linux (g++) but not on Mac OS.? 【发布时间】:2016-06-12 18:44:09 【问题描述】:

首先,我想为我的大代码道歉。我试图保持它的结构,但我对 C++ 编程仍然很陌生。

我在 OSX 上创建了一个 C++ 算法,它运行良好。然而,我需要在 Linux 上运行这个程序。在 Linux 上编译没有错误,但是当我运行程序时,它给出了以下错误:

Segmentation fault (core dumped)

我是调试代码的新手,并尝试使用 gdb 对其进行调试,但我不知道该如何继续。 gdb 给出的信息如下:

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;

我添加了下面的代码,它由一个主文件 c2f.cpp、一个头文件 c2f.hpp 和一个存储函数的附加文件 组成>c2f_functions.cpp.

当我通过引用一个名为 c2f_functions 的函数传递 3 个 lists 时,似乎发生了错误。此函数在 c2f_functions.cpp 脚本中。

我的问题是,

    我该如何解决这个问题? 为什么它在 OSX 下运行良好,而在 Linux 下却不行?

许多thnaks!

主文件 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);

头文件 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); 

函数文件 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;
  //=============================================================================//



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

【问题讨论】:

未定义行为的典型症状。 首先要做的是在 gdb 中键入bt 以获取回溯,这样您就可以看到您是如何到达出现错误的位置的。第二件事是更多地了解 gdb ;-) 【参考方案1】:

SYSSEGV 分段错误是由试图访问程序允许区域之外的内存引起的。在这种情况下,iter_old 或 iter_new 未初始化或包含与程序内存区域不对应的值。

它可能会在一个计算机系统上崩溃,而在另一个计算机系统上不会崩溃,因为 1) 不同的系统在未初始化的变量中可能有不同的值,以及 2) 不同的系统对程序可用内存的定义不同。

简而言之,寻找带有 SEGV 错误的坏指针值,并知道错误在不同系统上可能以不同的方式出现。

【讨论】:

问题确实出在iter_new。正如@max66 所指出的,当iter_new 被删除时,它就变成了一个指向无效对象的迭代器。我通过在删除项目以退出 for 循环并重新初始化迭代器后添加 break 解决了这个问题。非常感谢您花时间回答我的问题。【参考方案2】:

我不确定,但我怀疑问题在于您擦除了一个迭代器,然后使用(增量)它。

以下是关键部分

  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);
    
  

当你erase(iter_new)iter_new成为一个指向无效对象的迭代器;增加它 (iter_new++) 会给你(如果我没记错的话)一个未定义的值,下面的 iter_new-&gt;x 可能会导致你的程序出现分段错误。

我想一个解决方案可以是使用后缀增量调用erase(),以便erase() 调用iter_new 的副本,并且iter_new 在调用erase() 之前递增为有效的迭代器;像

  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.:对不起我的英语不好

【讨论】:

非常感谢,这有助于修复我的代码。问题确实在于删除iter_new。由于我只需要删除一项,因此我最终所做的是在删除 iter_new 后添加 break。这样,当项目被删除时,第二个 for 循环(我打破的那个)重新开始,迭代器重新开始,因此 iter_new 不能再指向无效对象。再次非常感谢您努力回答我的问题!

以上是关于linux (g++) 上的分段错误,但 Mac OS 上没有。?的主要内容,如果未能解决你的问题,请参考以下文章

Linux上的AVX分段错误[关闭]

分段错误:在 Mac 上为 11,但在 Linux 上没有,同时在 C 中创建数组

Mac OS 上“导入 cv”期间的“分段错误”

mac中的glTexParameteri分段错误

c++ segfault 在一个平台(MacOSX)但不是另一个(Linux)

编译FFMPEG时Mac上的g ++链接错误