0

我正在编写代码来用图像文件中的数据填充纹理类。据我所知,代码和实现是有效的,但是在进入我的程序的主循环时会导致分段错误。这 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;
}

我假设它与纹理指针有关,但是我尝试了几种方法来做同样的事情,它们都导致了相同的分段错误。有人可以解释是什么原因造成的吗?

4

2 回答 2

0

您的错误是因为 Texture 类不遵循三规则。'任何具有析构函数、复制构造函数或赋值运算符之一的类很可能需要全部三个'。

什么是三法则?

具体来说,可能发生的事情是因为您没有定义复制构造函数,所以您的对象被浅复制到向量中。这导致两个纹理对象共享相同的像素图数据。当其中一个对象被破坏时,这会使另一个对象中的像素图数据无效。

例如,复制构造函数的一种可能性是 this

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 提出了其他的可能性。

于 2013-04-28T21:35:37.627 回答
0

(注意:我假设Texture()正确分配了一个数组,或者至少将指针清零。如果它不这样做,那是你的问题。如果它只做后者,任何使用数组的尝试都会导致 UB,但是至少析构函数不会。)

如前所述,pixmap没有得到妥善处理。即使一个临时对象被销毁,它指向的数组也将被释放,在每个其他实例中都有悬空指针,而pixmap.

您可以添加一个复制构造函数和赋值运算符,为您复制指向的数组,满足“三规则”。但在我看来,更清洁的解决方案是遵循“零规则”。:) 使用自动进行复制和销毁的类型,并且您不需要特殊的函数来处理复制、分配和销毁。

如果应该复制数组,A std::vectoror可以很容易地做到这一点。std::array(您使用哪一个可能取决于数组是否需要调整大小。 std::vector将始终有效,但std::array对于静态大小数组的一些奇怪情况可能会更好。)

如果您需要共享数据,则std::shared_ptr(C++11) 或boost::shared_ptr会跟踪有多少指针。只有当它的所有shared_ptrs 都被销毁时,才会释放数组。

请注意,使用这些解决方案中的任何一个,都会为您处理数组的内存。如果这是析构函数等的唯一原因,那么您不再需要一个,因此“三规则”不再起作用。

于 2013-04-28T22:03:14.503 回答