无效写入导致的分段错误
Segmentation fault due to invalid writes
我正在尝试创建一个迷宫 class,它可以读取具有迷宫描述的输入流和 return 一个迷宫。但是,当我 运行 使用此给定输入流进行测试时:
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 函数中的每个图块分配 space,所以应该有 space 给我写。我还将 tile_collection 与我的构造函数堆叠在一起,因此当我调用 Maze(20,10) 时应该初始化 tile_collection,并且 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;
}
}
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;
Except,现在很明显你访问越界了。如果要写入位置 p
,则至少需要分配 p + 1
个元素,因为在 C++ 中几乎所有内容都是基于 0 的。
vector<Tile*>* tile_collection=new vector<Tile*>;
将初始化新的 local 变量并泄漏内存。与成员tile_collection
完全无关。如果 tile_collection
是类型 vector<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) { }
并稍微简化 setTile
:
void Maze::setTile(const Position &pos,Tile *tile){
tile_collection[pos.getX() + pos.getY() * Width] = tile;
}
我正在尝试创建一个迷宫 class,它可以读取具有迷宫描述的输入流和 return 一个迷宫。但是,当我 运行 使用此给定输入流进行测试时:
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 函数中的每个图块分配 space,所以应该有 space 给我写。我还将 tile_collection 与我的构造函数堆叠在一起,因此当我调用 Maze(20,10) 时应该初始化 tile_collection,并且 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;
}
}
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;
Except,现在很明显你访问越界了。如果要写入位置 p
,则至少需要分配 p + 1
个元素,因为在 C++ 中几乎所有内容都是基于 0 的。
vector<Tile*>* tile_collection=new vector<Tile*>;
将初始化新的 local 变量并泄漏内存。与成员tile_collection
完全无关。如果 tile_collection
是类型 vector<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) { }
并稍微简化 setTile
:
void Maze::setTile(const Position &pos,Tile *tile){
tile_collection[pos.getX() + pos.getY() * Width] = tile;
}