我有这样一个类,其中唯一的属性是一个向量〈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);
}
}
}
之后,我将数据从1d矢量传输到2d矢量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];
}
使用这段代码,我在调整大小的行中得到了一个分段错误。
有人能告诉我正确的方法吗?
更新
完整代码分为这2个项目:https://github.com/klebermo/codec包含实现读取方法的Netpbm和Bitmap类。https://github.com/klebermo/game使用上一链接中的方法。
1条答案
按热度按时间ccrfmcuu1#
就像其他人说的,错误不在你发布的代码片段中,这就是为什么人们希望有一个最小的可复制的自包含代码示例,以缩小错误的范围。
实际错误(或其中一个实际错误)在此行中:
以更扩展的形式写出这个表达式意味着:
这意味着在这一行之后访问
vertices
会导致未定义的行为,特别是写入它会经常损坏其他对象。为了避免这种情况,你可以让向量和
vertices
保持相同的持续时间,另外,不要在一个由std::vector管理的指针上调用delete
。这样,只要
vertices_vec
没有超出范围,vertices
就会一直指向有效数据。编辑:
另外,我猜图像读入代码并不是在所有情况下都有边界检查,所以如果输入文件无效,你可能会遇到其他问题。所以你可以在那里添加一些带有边界检查的Assert/调试检查。
编辑2:
你违反了一个定义规则。
在一个标头(
Netpbm/src/netpbm.hpp
)中,您有而在另一个标头(
Netpbm/include/netpbm.hpp
)中,您有这两个向量的大小不同,你编译的部分代码采用一种大小,而其他部分代码采用另一种大小,因此破坏了堆栈。如果使用的代码不知道向量应该在那里,那么生成的构造函数将永远不会初始化它,所以你访问的是一个你从未调用过构造函数的向量。