无效写入导致分段错误



我正在尝试创建一个迷宫类,该类可以读取具有迷宫描述的输入流并返回迷宫。然而,当我用这个给定的输入流运行测试时:

20 10
####################
#................<.#
#..................#
#...###............#
#.....#............#
#.....#............#
#...###............#
#..................#
#..................#
####################

它给出了一个分段错误,我在valgrind上运行对象文件来检查发生了什么:

Invalid write of size 8
==2482545==    at 0x4032CD: Maze::setTile(Position const&, Tile*) (maze.cpp:47)
==2482545==    by 0x40347B: Maze::read(std::istream&) (maze.cpp:67)
.....
==2482545==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

我真的不明白为什么在我的代码中存在分段错误或无效写入,我应该在setTile函数中为每个tile分配空间,所以应该有空间供我写入。我还将tile_collection与构造函数堆叠在一起,因此当我调用Maze(20,10(时,tile_collective应该被初始化,并且setTile内部的大小调整应该可以工作。你能指出我遗漏了什么吗?提前谢谢。

Maze::Maze(int width,int height):
Width(width),Height(height){
vector<Tile*>* tile_collection=new vector<Tile*>;
}

void Maze::setTile(const Position &pos,Tile *tile){
tile_collection.resize(pos.getX()+pos.getY()*Width);
tile_collection[pos.getX()+pos.getY()*(Width)]=tile;
}

Maze *Maze::read(std::istream &in){
int x;int y;char c;
if ((in>>x)&&(in>>y)){
Maze *new_maze=new Maze(x,y);
//loop over the specified maze dimension
for (int i=0;i<y;i++){
for (int j=0;j<x;j++){
if (in>>c){
//using tilefactory to change character into a tile
TileFactory *fac=fac->getInstance();
Tile* temp=fac->createFromChar(c);
//if createFromChar fails, return nullptr, otherwise set tile at position j,i
if (temp==nullptr){
return nullptr;
}
else{
new_maze->setTile(Position(j,i),temp);
}
}
}
}
return new_maze;
}
else{
return nullptr;
}
}

vector<Tile*>* tile_collection=new vector<Tile*>;将初始化新的本地变量并泄漏内存。它与成员tile_collection完全无关。如果tile_collectionvector<Tile*>类型的成员变量(即而不是指针(,则构造函数将在没有任何显式代码的情况下对其进行初始化。

第二

tile_collection.resize(pos.getX()+pos.getY()*Width);
tile_collection[pos.getX()+pos.getY()*(Width)]=tile;

导致越界访问。对于大小为n的向量,有效索引为0...n-1。似乎还有一个逻辑错误。每次写入内容时,都会调整向量的大小(也会减小其大小,例如当pos接近(0, 0)时(。也许你想要更像这样的东西:

除非迷宫不能动态增长,否则你只需要调整向量一次大小,或者如果大小正确,则初始化:

Maze::Maze(int width, int height):
Width(width),
Height(height),
tile_collection(width * height) { }

并将CCD_ 9简化一位:

void Maze::setTile(const Position &pos,Tile *tile){
tile_collection[pos.getX() + pos.getY() * Width] = tile;
}
tile_collection.resize(pos.getX()+pos.getY()*Width);
tile_collection[pos.getX()+pos.getY()*(Width)]=tile;

与相同

int p = pos.getX()+pos.getY()*Width;
tile_collection.resize(p);
tile_collection[p]=tile;

不过,现在很明显,您正在访问越界。如果您想写入位置p,您需要至少分配p + 1元素,因为在C++中,几乎所有内容都是基于0的。

最新更新