我有一个继承自类案例的类Block:
class Case {
public:
Case(sf::Vector2f const& pos, sf::IntRect const& textureRect, int type = 1);
protected:
int type_;
sf::Vector2f pos_;
sf::FloatRect hitBox_;
sf::IntRect textureRect_;
};
class Block : public Case {
public:
Block(sf::Texture* const& texture, sf::Vector2f const& pos, sf::IntRect const& textureRect, int const& type = 2);
sf::Sprite& getSprite();
private:
std::shared_ptr<sf::Texture> texture_;
sf::Sprite sprite_;
};
(这两个构造函数都是非常基本的,我在任何地方都不会使用任何新的东西)
并且我有一个unordered_map的无序地图来存放我的积木:
std::unordered_map<int, std::unordered_map<int, Block>> blocks_;
但是当我尝试删除一个时:
if(blocks_[i%lenght].find((i-i%lenght)/lenght) != blocks_[i%lenght].end())
blocks_[i%lenght].erase((i-i%lenght)/lenght);
我得到了错误:
double free or corruption (out)
我尝试打印析构函数,在出现此错误之前,仅调用了Block中的析构函数。
已经找到了大约2个小时的解决方案,所以我终于在这里问了,谢谢!
答案 0 :(得分:3)
您的问题出在构造函数上
Block::Block(sf::Texture *const &texture, sf::Vector2f const &pos,
sf::IntRect const &textureRect, int const &type)
: Case(pos, textureRect, 2), texture_(texture),
sprite_(*texture_, textureRect_) {}
虽然用这种方式写不一定不一定是错误的,但是如果将相同的Texture传递给多个块,那将是错误的:
sf::Texture *tex = new sf::Texture(/* ... params ... */);
Block b1(tex, /* ... remaining params ... */);
Block b2(tex, /* ... remaining params ... */);
现在有两个独立的shared_ptr
认为它们是tex
的唯一所有者,因此,一旦删除了其中一个块,纹理也将被删除,因此如果两个块都被删除,则您有双重免费。
您的代码应如下所示:
Block::Block(const std::shared_ptr<sf::Texture> &texture, sf::Vector2f const &pos,
sf::IntRect const &textureRect, int const &type)
: Case(pos, textureRect, 2), texture_(texture),
sprite_(*texture_, textureRect_) {}
您应该像这样构造Blocks
:
std::shared_ptr<Texture> tex = std::make_shared<Texture>(/* ... params ... */);
Block b1(tex, /* ... remaining params ... */);
Block b2(tex, /* ... remaining params ... */);
这并不意味着您永远不要使用原始指针。如果您例如会具有将纹理绘制到屏幕上的功能,那么原始指针就可以了:
void draw_texture( sf::Texture * const tex) {
// do some drawing but don't store tex somewhere
// so tex is only used within that draw_texture call
}
然后您将这样称呼它:
std::shared_ptr<Texture> tex = std::make_shared<Texture>(/* ... params ... */);
draw_texture(tex.get());