繁体   English   中英

无法访问向量的元素<vector<?> &gt; </vector<?>

[英]Unable to access elements of vector<vector<?>>

我有这个类,其中唯一的属性是 vector<vector<?>> 像这样:

struct Pixel {
    float r, g, b;
};

class Test {
private:
  vector<vector<struct Pixel>> pixels;
public:
  void read(std::string filename);
}

方法 read 是我首先从文件中读取数据并放入一维数组的地方:

std::vector<pixel> v;

while(getline(file, line_pixels)) {
  if(line_pixels.size() > 0 && line_pixels.at(0) != '#') {
    std::stringstream ss(line_pixels);
    std::string value;
    while(getline(ss, value, ' ')) {
      pixel p;
      p.r = p.g = p.b = stoi(value);
      v.emplace_back(p);
    }
  }
}

之后,我将数据从这个一维向量传输到二维向量pixels 我试图通过这两种方式做到这一点:

int index = 0;
size_t h = stoi(height), w = stoi(width);
for(size_t i=0; i<h; i++) {
  std::vector<pixel> row;
  for(size_t j=0; j<w; j++)
    row.push_back(v[index++]);
  pixels.push_back(row);
}

使用此代码,当我尝试使用pixel[index]之类的内容访问像素中的任何元素时,出现分段错误。

我尝试过的另一个选择是:

size_t h = stoi(height), w = stoi(width);
pixels.resize(h);
for(size_t i=0; i<h; i++)
  pixels[i].resize(w);
for(size_t i=0; i<v.size(); i++) {
  int row = i / w;
  int col = i % w;
  pixels[row][col] = v[i];
}

使用此代码,我在该调整大小行中遇到了分段错误。

任何人都可以告诉我正确的方法吗?

更新

完整代码分为这两个项目: https ://github.com/klebermo/codec 包含实现读取方法的类 Netpbm 和 Bitmap。 https://github.com/klebermo/game使用上一个链接中的方法。

就像其他人所说的那样,错误不在您发布的代码片段中。 这就是为什么人们想要一个最小的可重现的独立代码示例,以缩小错误范围。

实际错误(或实际错误之一)在此行中:

float * vertices = image.toArray().data();

以更扩展的形式写出这个表达式意味着:

float * vertices;
{
    std::vector<float> temp = image.toArray();
    vertices = temp.data();
} // temp gets destroyed here, since it goes out of scope.
// accessing vertices after this point is undefined behavior
// because the memory it points to was deleted by the 
// destructor of temp

这意味着对该行之后的vertices的访问会导致未定义的行为,尤其是写入它会经常破坏其他对象。

您可以将向量保持与vertices相同的持续时间以避免这种情况。 此外,不要对由 std::vector 管理的指针调用delete

std::vector<float> vertices_vec = image.toArray();
float *vertices = vertices_vec.data();

这样,只要vertices_vec不超出范围, vertices就会一直指向有效数据。

编辑:

此外,我猜图像读入代码在所有情况下都没有边界检查,因此如果输入文件无效,您可能会在那里遇到其他问题。 因此,您可以在其中添加更多带有边界检查的断言/调试检查。

编辑2:

您违反了单一定义规则。

在一个标题中( Netpbm/src/netpbm.hpp )你有

class Netpbm {
protected:
  std::vector<std::vector<pixel>> pixels;
public:
  virtual void read_file(std::string file_name) = 0;
  virtual void write_ascii_file(std::string file_name) = 0;
  virtual void write_binary_file(std::string file_name) = 0;

  int getHeight();
  int getWidth();
  std::vector<float> toArray();
};

在另一个标头( Netpbm/include/netpbm.hpp )中你有

class Netpbm {
public:
  virtual void read_file(std::string file_name) = 0;
  virtual void write_ascii_file(std::string file_name) = 0;
  virtual void write_binary_file(std::string file_name) = 0;

  int getHeight();
  int getWidth();
  std::vector<float> toArray();
};

这两个具有不同的大小,您正在编译代码的一部分假设一个大小,而代码的其他部分假设另一个大小。 因此破坏堆栈。 如果使用代码不知道向量应该在那里,那么生成的构造函数将永远不会初始化它,因此您正在访问一个从未调用过构造函数的向量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM