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->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 上没有。?的主要内容,如果未能解决你的问题,请参考以下文章
分段错误:在 Mac 上为 11,但在 Linux 上没有,同时在 C 中创建数组