c++ - 由于无效写入导致的段错误

标签 c++ class debugging segmentation-fault valgrind

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

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 函数中的每个图 block 分配空间,所以应该有空间供我编写。我还将 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;
  }
}


最佳答案

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 的 vector 有效索引为 0...n-1 .
似乎也存在逻辑错误。每次向其写入内容时都会调整 vector 的大小(您也会减小它的大小,例如当 pos 接近 (0, 0) 时)。也许你想要更像这样的东西:

除非迷宫不能动态增长,否则您只需要调整一次 vector 的大小,或者如果使用正确的大小进行初始化:
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;
}

关于c++ - 由于无效写入导致的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61489117/

相关文章:

c++ - 使用 Absdiff 的 OpenCV 背景减法

c++ - 让模板采用类型或值

java - 返回序列化对象(如果存在)否则返回新实例?

c++ - 为什么断言宏仅用于调试构建

xcode - 在监视全局变量的 XCode 上设置条件断点

java - 嵌入式 Groovy 控制台——如何共享整个状态

C++计算GFlops

c++ - 如何将用户输入与字符串进行比较?

c++ - C++ 中的枚举 : how to pass as parameter?

python - 连接类、静态还是实例?