C ++ Memory Leak on function argument

时间:2015-12-11 17:05:35

标签: c++ memory-leaks

所以我会直截了当地说:我有一个函数可以向另一个类添加一些东西(恰好是一个类):

tower->set_weapon(new NoWeapon());

set_weapon()是塔类中的一个简单方法,它将内部变量与它接收的新的NoWeapon类相关联。

virtual void set_weapon(Weapon* weapon){ weapon_ = weapon; };

weapon_是指向武器类的指针,NoWeapon是层次结构的武器之子。当一切都说完了,塔楼就会清理一切:

weapon_->Clean();
delete weapon_;

然而,我仍然得到内存泄漏。我在VisualStudio 2013上使用vld,它在我提到的第一行检测到内存泄漏

tower->set_weapon(new NoWeapon());

知道为什么会这样,我怎么能解决它?

提前谢谢!

编辑:感谢YSC的解决方案。事实上,我没有初始化原始武器指针,但是你的想法让我重回正轨。

至于unique_ptr的想法,我之前玩过它,但它不是我想要的解决方案。无论如何,谢谢你的帮助。

2 个答案:

答案 0 :(得分:2)

我们缺少上下文信息,但基本上如果Tower::set_weapon()被调用两次,Tower::weapon_会被覆盖并且内存泄漏。建议:

Tower::Tower()
    : weapon_(nullptr)
{}

void Tower::set_weapon(Weapon* weapon)
{
    if (weapon_ != nullptr)
    {
        weapon_->Clean(); // should be called by Weapon::~Weapon()
    }
    delete weapon_;
    weapon_ = weapon;
};

您还可以使用std::unique_ptr

class Tower
{
    std::unique_ptr<Weapon> weapon_;

public:
    Tower::Tower() {}

    void set_weapon(std::unique_ptr<Weapon> weapon)
    {
        // assume Weapon::~Weapon() is fixed
        weapon_ = std::move(weapon);
    };
};

答案 1 :(得分:1)

注意:YSC的回答是正确的。武器应该不需要Clean方法,因为它可以在析构函数中处理资源释放。

但是,如果对Clean的调用确实有某些原因,您可以使用自定义删除工具将所有这些内容封装在std::unique_ptr中。

像这样:

struct weapon_cleaner
{
  void operator()(Weapon* pw) const nothrow {
    if (pw) {
      try {
        pw->Clean();
      }
      catch(...) {
      }
    }
    delete pw;
  }
};

using weapon_pointer = std::unique_ptr<Weapon, weapon_cleaner>;

class Tower
{
    weapon_pointer weapon_;

public:
    Tower::Tower() {}

    void set_weapon(weapon_pointer weapon)
    {
        weapon_ = std::move(weapon);
    };
};

这样称呼:

weapon_pointer make_machine_gun() {
  return weapon_pointer(new MachineGun(), 
                        weapon_cleaner());
}

mytower.set_weapon(make_machine_gun());