[英]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.