c ++ Segmentation Fault将指针传递给函数

时间:2013-04-28 21:28:49

标签: c++ segmentation-fault

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

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

2 个答案:

答案 0 :(得分:0)

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

What is The Rule of Three?

具体可能发生的事情是因为你没有定义一个复制构造函数,你的对象被浅复制到向量中。这导致两个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::vectorstd::array可以轻松完成此操作。 (您使用哪一个可能取决于数组是否需要调整大小。std::vector将始终有效,但std::array对于使用静态大小数组的奇数情况可能更好。)

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

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

相关问题