我目前正在为我的AI课模拟自动驾驶汽车。汽车的构造函数将板子作为参数接收,因此它可以设置汽车的位置并将第一个节点添加到搜索树,从而可以从中搜索最佳路径。从起始位置到结束位置。问题是,电路板生成时没有任何问题,但是当我尝试将其传递给汽车的构造函数时,会导致Segmentation fault (core dumped)
错误。
我使用了调试器(gdb),在其中运行代码并进行了追溯。问题出在这里:
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL) //This line's the problem
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
注意:'children_'最多包含search_tree节点的4个子级,并且是我必须创建的自定义vector_c类。
这是失败的运算符及其调用的功能
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
我认为在比较if (children_[i] == NULL)
中可能是类型错误,所以我做了一个自定义运算符,它返回了一个对象(TDato),而不是对一个对象(TDato&)的引用,但是它不起作用
我无法想象是什么原因造成的和/或如何解决。
谢谢。
编辑1:这是项目的google drive link,因为即使是最小的可重现示例也太大了,难以在Stack Overflow问题中阅读。我保证它不是很大(小于1 MB)。
编辑2:,这是我能做的最大的事情,以使可重现的示例最小化,因为未包含该示例而使该问题告终。
main.cpp
#include "../include/board_s.hpp"
#include "../include/car_c.hpp"
using namespace std;
int main(void)
{ board_s<int> board(20, 20);
board.file_depiction();
car_c car(board);
board.write(cout);
return 0;
}
在这里,问题出现在调用car_c的构造函数时。它应该创建一个car_c对象。
board_c.hpp
#ifndef __BOARD_S__
#define __BOARD_S__
#include <cstdio>
#include <iostream>
#include <cstring>
#include <random>
#include <fstream>
#include <utility>
#include "matrix_c.hpp"
#include "tree_c.hpp"
using namespace std;
template <typename TDato = int>
class board_s: public matrix_c<TDato>
{ private:
pair<int, int> starting_pos;
pair<int, int> finishing_pos;
public:
board_s(int, int);
~board_s(void);
pair<int, int> get_start(void);
void file_depiction(void); //Generates obstacles and starting/finishing points as depicted in board_depiction.txt.
virtual ostream& write(ostream&);
int distance(pair<int, int>&) const; //Returns the distance from a given position to the finishing point
private:
bool object_setter(string, int&, int&);
int object_identifier(string&) const; //Given the name of the object ("NEW OBSTACLE" [1], "STARTING POSITION" [2] or "FINISHING POSITION" [3]) returns it's code
};
template class board_s<int>;
#endif
board_c.cpp
#include "../include/board_s.hpp"
#include "matrix_c.cpp"
using namespace std;
//The constructor fills the board with empty boxes.
template <typename TDato>
board_s<TDato>::board_s(int m, int n):
matrix_c<TDato>::matrix_c(m + 2, n + 2)
{ for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
matrix_c<TDato>::at(i, j) = 0;
for(int i = 0; i < n + 2; i++)
{ matrix_c<TDato>::at(0, i) = 1;
matrix_c<TDato>::at(m + 1, i) = 1;
}
for(int i = 0; i < m + 2; i++)
{ matrix_c<TDato>::at(i, 0) = 1;
matrix_c<TDato>::at(i, n + 1) = 1;
}
starting_pos.first = 0;
starting_pos.second = 0;
finishing_pos.first = 0;
finishing_pos.second = 0;
}
template <typename TDato>
board_s<TDato>::~board_s(void){}
template <typename TDato>
pair<int, int> board_s<TDato>::get_start(void) { return starting_pos; }
template <typename TDato>
void board_s<TDato>::file_depiction(void)
{ string line;
int x, y, i;
std::ifstream bd;
bd.open("board_depiction.txt");
if (bd.is_open())
{ getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
matrix_c<TDato>::resize(x + 2, y + 2);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("STARTING POSITION", x, y);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("FINISHING POSITION", x, y);
while (getline(bd, line))
if (line[0] != 'O')
{ i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("NEW OBSTACLE", x, y);
}
}
else cout << "ERROR";
}
template <typename TDato>
ostream& board_s<TDato>::write(ostream& os)
{ int temp = matrix_c<TDato>::get_n() - 2 + (4 * (matrix_c<TDato>::get_n() - 2));
os << " ";
for (int i = 1; i < temp; i++)
os << "_";
os << " " << endl << "|";
for (int i = 1; i < matrix_c<TDato>::get_m() - 1; i++)
{ for (int j = 0; j < 2; j++)
{ for (int k = 1; k < matrix_c<TDato>::get_n() - 1; k++)
switch (matrix_c<TDato>::at(i, k))
{ case 1:
os << "████|";
break;
case 2:
if (j == 0)
os << " CC |";
else os << "_CC_|";
break;
case 3:
if (j == 0)
os << " FF |";
else os << "_FF_|";
break;
default:
if (j == 0)
os << " |";
else os << "____|";
}
os << endl;
if (j == 0) os << "|";
}
if (i < matrix_c<TDato>::get_m() - 2) os << "|";
}
os << endl;
return os;
}
template <typename TDato>
int board_s<TDato>::distance(pair<int, int>& pos) const
{ int d = (finishing_pos.first - pos.first) + (finishing_pos.second - pos.second);
if (d < 0) return (d * (-1));
else return d;
}
template <typename TDato>
bool board_s<TDato>::object_setter(string name, int &x, int &y)
{ if((x > 0) && (x < matrix_c<TDato>::get_m() - 1) && (y > 0) && (y < matrix_c<TDato>::get_n() - 1) && (matrix_c<TDato>::at(x, y) == 0))
{ matrix_c<TDato>::at(x, y) = object_identifier(name);
cout << endl << endl << "The " << name << " has been set in (" << x << ", " << y << ")" << endl;
if (name == "STARTING POSITION")
{ starting_pos.first = x;
starting_pos.second = y;
}
else if (name == "FINISHING POSITION")
{ finishing_pos.first = x;
finishing_pos.second = y;
}
return true;
}
else
{ cout << endl << "The coordinates that you intriduced were out of reach or the position wasn't free." << endl;
return false;
}
}
template <typename TDato>
int board_s<TDato>::object_identifier(string &name) const
{ if (name == "NEW OBSTACLE")
return 1;
else if (name == "STARTING POSITION")
return 2;
else if (name == "FINISHING POSITION")
return 3;
else return 0;
}
matrix_c.hpp
#ifndef __MATRIX_C__
#define __MATRIX_C__
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include "vector_c.hpp"
using namespace std;
template <typename TDato>
class matrix_c //Template matrix class implemented with a vector.
{ private:
int m_;
int n_;
vector_c<TDato> v_;
public:
matrix_c(void); //Empty constructor
matrix_c(int, int); //Constructor with dimensions
~matrix_c(void);
void resize(int, int);
TDato& at (int, int); //Redirects to position (x, y)
virtual TDato& operator()(int, int); //Operator for at(int, int)
int get_m(void) const;
int get_n(void) const;
private:
int pos(int, int);
protected:
int ctoi(char&) const;
int strtoi(string&, int&) const;
};
#endif
matrix_c.cpp
#include "../include/matrix_c.hpp"
using namespace std;
template <typename TDato>
matrix_c<TDato>::matrix_c(void):
m_(0),
n_(0),
v_() {}
template <typename TDato>
matrix_c<TDato>::matrix_c(int m, int n):
m_(m),
n_(n),
v_(m * n) {}
template <typename TDato>
matrix_c<TDato>::~matrix_c(void) {}
template <typename TDato>
void matrix_c<TDato>::resize(int m, int n)
{ v_.resize(m * n);
m_ = m;
n_ = n;
}
template <typename TDato>
TDato& matrix_c<TDato>::at(int i, int j) { return v_[(pos(i,j))]; }
template <typename TDato>
TDato& matrix_c<TDato>::operator()(int i, int j) { return at(i,j); }
template <typename TDato>
int matrix_c<TDato>::get_m(void) const { return m_; }
template <typename TDato>
int matrix_c<TDato>::get_n(void) const { return n_; }
template <typename TDato>
int matrix_c<TDato>::pos(int i, int j) { return ((n_ * i) + j); }
template <typename TDato>
int matrix_c<TDato>::ctoi(char &c) const
{ int n = c;
return n - 48;
}
template <typename TDato>
int matrix_c<TDato>::strtoi(string &s, int& i) const
{ int n = 0;
int mult = 1;
while ((s[i] != ' ') && (i >= 0))
{ n += ctoi(s[i]) * mult;
mult *= 10;
i--;
}
return n;
}
template class matrix_c<int>;
vector_c.hpp
#ifndef __VECTOR_C__
#define __VECTOR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
using namespace std;
template <typename TDato>
class vector_c
{ private:
int sz_;
TDato* data_;
public:
vector_c(void); //Empty constructor
vector_c(int); //Constructor with size
~vector_c(void);
TDato& get_data(int) const;
void set_data(TDato&, int);
ostream& write(ostream&) const;
TDato& operator [](int);
void resize(int);
private:
void new_vector(void);
void del_vector(void);
};
#endif
vector_c.cpp
#include "../include/vector_c.hpp"
#include "../include/node_c.hpp"
using namespace std;
template <typename TDato>
vector_c<TDato>::vector_c(void):
sz_(0),
data_(NULL) {}
template <typename TDato>
vector_c<TDato>::vector_c(int size):
sz_(size),
data_(new TDato[sz_]) {}
template <typename TDato>
vector_c<TDato>::~vector_c(void)
{ delete[] data_;
data_ = NULL;
}
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
template <typename TDato>
void vector_c<TDato>::set_data(TDato& dat, int a) { data_[a] = dat;}
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
void vector_c<TDato>::resize(int sz)
{ del_vector();
sz_ = sz;
new_vector();
}
template <typename TDato>
void vector_c<TDato>::new_vector(void){
data_ = new TDato[sz_];
}
template <typename TDato>
void vector_c<TDato>::del_vector(void)
{ if (data_ != NULL){
delete [] data_;
data_ = NULL;
}
}
template class vector_c<int>;
template class vector_c<node_c*>;
node_c.hpp
#define MAX_CHILDREN 4
#ifndef __NODE_C__
#define __NODE_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "vector_c.hpp"
using namespace std;
class node_c
{ private:
node_c* parent_;
vector_c< node_c* > children_;
pair<pair<int, int>, int> data_;
public:
node_c(void);
node_c(int &x, int &y, int &cost);
node_c(pair<pair<int, int>, int>&);
~node_c(void);
void add_child(node_c*);
};
#endif
node_c.cpp
#include "../include/node_c.hpp"
using namespace std;
node_c::node_c(void):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
node_c::node_c(int &x, int &y, int &cost):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = x;
data_.first.second = y;
data_.second = cost;
}
node_c::node_c(pair<pair<int, int>, int> &dat):
parent_(NULL),
data_(dat)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
}
node_c::~node_c(void)
{ parent_ = NULL;
for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL)
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
tree_c.hpp
#ifndef __TREE_C__
#define __TREE_C__
#include "node_c.hpp"
using namespace std;
class tree_c
{ private:
node_c* root_;
int depth_;
public:
tree_c(void);
tree_c(node_c*);
node_c* add_node(node_c*, int&, int&, int);
};
#endif
tree_c.cpp
#include "../include/tree_c.hpp"
using namespace std;
tree_c::tree_c(void):
root_(NULL),
depth_(0) {}
tree_c::tree_c(node_c* root):
root_(root),
depth_(1) {}
node_c* tree_c::add_node(node_c* parent, int& x, int& y, int cost)
{ node_c* node = new node_c(x, y, cost);
parent->add_child(node);
}
car_c.hpp
#ifndef __CAR_C__
#define __CAR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "tree_c.hpp"
#include "board_s.hpp"
using namespace std;
class car_c
{ private:
tree_c tree_;
pair<int, int> pos_;
matrix_c<int> visited_;
public:
car_c(void);
car_c(board_s<int>&);
~car_c(void);
};
#endif
car_c.cpp
#include "../include/car_c.hpp"
using namespace std;
car_c::car_c(void):
tree_(NULL)
{ pos_.first = 0;
pos_.second = 0;
}
car_c::car_c(board_s<int>& board):
pos_(board.get_start()),
tree_(tree_.add_node(NULL, pos_.first, pos_.second, 0))
{ visited_(pos_.first, pos_.second) = 1; }
car_c::~car_c(void) {}
调试信息:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=@0x7ffffffeddf0: 8, y=@0x7ffffffeddf4: 0,
cost=@0x7ffffffedd2c: 0) at src/node_c.cpp:20
20 children_[i] = NULL;
(gdb) bt
#0 0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=@0x7ffffffeddf0: 8, y=@0x7ffffffeddf4: 0,
cost=@0x7ffffffedd2c: 0) at src/node_c.cpp:20
#1 0x0000000000402007 in tree_c::add_node (this=0x7ffffffedde0, parent=0x0, x=@0x7ffffffeddf0: 8,
y=@0x7ffffffeddf4: 0, cost=0) at src/tree_c.cpp:16
#2 0x0000000000402df6 in car_c::car_c (this=0x7ffffffedde0, board=...) at src/car_c.cpp:15
#3 0x0000000000401403 in main () at src/main.cpp:11
很抱歉,我的提问时间太长了,但这是我能做的最小的可复制示例。如果您知道重新创建错误的另一种方法,请告诉我,以便我进行改进。