我正在编写代码以使用图像文件中的数据填充纹理类。据我所知,代码和实现工作,但它导致进入我的程序的主循环时出现分段错误。删除这4行后,删除分段错误:
Texture* texture = new Texture(); // Dynamically allocate texture object to texture pointer
bool success = loadTexture(texture, "C:/pathToImage/image.png"); // Function that gets image data
cout << success << endl; // Print out success or not
textures.push_back(*texture); // put texture in a vector of textures
编辑:texture.h
class Texture {
public:
Texture();
Texture(const Texture&);
~Texture();
Texture& operator=(const Texture&);
public:
void init();
int width, height;
std::vector<unsigned char> pixmap;
GLuint id;
};
texture.cpp :( init函数被删除,因为它与错误无关,甚至不会被调用。)
Texture::Texture() : width(0), height(0), pixmap(), id(int(-1)){}
Texture::Texture(const Texture& other) : width(other.width), height(other.height), pixmap(other.pixmap), id(other.id){}
Texture::~Texture()
{
width = 0;
height = 0;
delete &pixmap;
id = int(-1);
}
Texture& Texture::operator=(const Texture& other) {
width = other.width;
height = other.height;
pixmap = other.pixmap;
id = other.id;
}
我假设它与纹理指针有关,但是我尝试了几种方法来做同样的事情,并且它们都导致了相同的分段错误。有人可以解释是什么导致了这个吗?
答案 0 :(得分:0)
您的错误是因为Texture类不遵循三条规则。 '任何具有析构函数,复制构造函数或赋值运算符的类都很可能需要全部三个'。
具体可能发生的事情是因为你没有定义一个复制构造函数,你的对象被浅复制到向量中。这导致两个Texture对象共享相同的像素图数据。当其中一个对象被破坏时,这会使另一个对象中的像素图数据无效。
例如,复制构造函数的一种可能性是
Texture::Texture(const Texture& other) : width(other.width), height(other.height), pixmap(NULL), id(other.id)
{
pixmap = new unsigned char[width*height];
memcpy(pixmap, other.pixmap, width*height);
}
只有一种方法可以做到这一点。 cHao建议其他可能性。
答案 1 :(得分:0)
(注意:我假设Texture()
正确分配了一个数组,或者至少将指针归零。如果它没有做任何一个,那就是你的问题。如果它只做了后者,那么任何尝试使用数组会导致UB,但至少析构函数不会。)
如上所述,pixmap
未得到妥善处理。如果甚至一个临时对象被销毁,它指向的数组将被释放,在pixmap
中具有相同指针的每个其他实例中留下悬空指针。
您可以添加一个复制构造函数和赋值运算符,为您复制指向数组,实现“三规则”。但在我看来,一个更清洁的解决方案是遵循“rule of zero”。 :)使用自动执行复制和销毁的类型,您无需使用特殊函数来处理复制,赋值和销毁。
如果要复制数组,std::vector
或std::array
可以轻松完成此操作。 (您使用哪一个可能取决于数组是否需要调整大小。std::vector
将始终有效,但std::array
对于使用静态大小数组的奇数情况可能更好。)
如果您需要共享数据,std::shared_ptr
(C ++ 11)或boost::shared_ptr
将跟踪有多少指针。只有当它的所有shared_ptr
都被销毁时,才会释放数组。
请注意,对于任何这些解决方案,都会为您处理阵列的内存。如果这是析构函数等的唯一原因,那么你不再需要一个,因此“三规则”不再起作用。