c ++分段错误将指针传递给函数
Posted
技术标签:
【中文标题】c ++分段错误将指针传递给函数【英文标题】:c++ Segmentation Fault passing in pointer to function 【发布时间】:2013-04-28 21:28:48 【问题描述】:我正在编写代码来用图像文件中的数据填充纹理类。据我所知,代码和实现是有效的,但是在进入我的程序的主循环时会导致分段错误。这 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;
我假设它与纹理指针有关,但是我尝试了几种方法来做同样的事情,它们都导致了相同的分段错误。有人能解释一下是什么原因造成的吗?
【问题讨论】:
请提供更多代码。到目前为止,您所展示的内容不足以看到问题。 我猜 Texture 不遵循三规则。 @Kyurem 你想要什么?这是我拥有的唯一导致错误的代码 - 删除它会删除错误。 杀死指针。在这里没用。 您动态分配纹理,然后将其副本放入纹理中,这很奇怪,尽管不一定是错误的。 【参考方案1】:您的错误是因为 Texture 类没有遵循三规则。 '任何具有析构函数、复制构造函数或赋值运算符之一的类很可能需要全部三个'。
What is The Rule of Three?
具体可能发生的情况是,由于您尚未定义复制构造函数,因此您的对象被浅复制到向量中。这导致两个纹理对象共享相同的像素图数据。当其中一个对象被破坏时,这会使另一个对象中的像素图数据无效。
例如,复制构造函数的一种可能性是 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 提出了其他可能性。
【讨论】:
根据是否应该共享pixmap
数组,您还可以使用指向它的智能指针(需要 C++11 或 Boost,或其他一些具有良好共享指针的库),或者vector<char>
,将为您复制。两者都可以避免甚至需要析构函数,更不用说其他两个了。
致力于实施上述“三法则”。直到现在我才意识到这一点,感谢您的提醒。
同样的错误仍然适用,即使在实施了三规则之后。有关新的纹理类,请参阅上面的更新帖子
@ColinMoore:构造函数和赋值运算符是否为pixmap
分配了一个新数组?仅复制指针会给您带来与默认函数相同的问题。
Texture operator=(Texture);
应该是Texture& operator=(const Texture&);
也许你可以给我们看一下析构函数、复制构造函数等的代码。【参考方案2】:
(注意:我假设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
s 都被销毁时,数组才会被释放。
请注意,使用这些解决方案中的任何一种,都会为您处理数组的内存。如果这是析构函数等的唯一原因,那么您不再需要一个,因此“三规则”不再起作用。
【讨论】:
我应用了你所说的,用矢量替换了像素图。发生同样的错误,这次是在程序的前面。 @ColinMoore:你用NULL
初始化它,就像你用指针做的那样?那不会飞让它自己创建,在你使用它之前,resize
它的大小可以容纳你需要的数据。对我来说,这似乎是您的主要问题;我没有看到你甚至用可用值填充了指针pixmap
。
如果您查看我帖子中更新的构造函数,我想它会回答您的问题。我使用默认构造函数对其进行初始化。而且您看不到我在哪里填充了可用值,因为这是在传递指向纹理的指针的函数中完成的。
@ColinMoore 你不会删除向量。如果使用向量,则可以删除析构函数、复制构造函数和赋值运算符。我认为您应该花时间阅读我发布的关于三规则的链接。或者读一本书,任何好的 C++ 书籍都会广泛涉及这个主题,如果不了解资源管理和对象复制的问题,你真的无法正确编程 C++。
@ColinMoore:请不要更改问题中已有的代码。它使所有答案无效;现在看起来我在告诉你做你已经在做的事情。如果您想提及您的更改,请在问题的现有内容之后添加“更新:”或其他内容。以上是关于c ++分段错误将指针传递给函数的主要内容,如果未能解决你的问题,请参考以下文章