函数参数的C++内存泄漏

函数参数的C++内存泄漏,c++,memory-leaks,C++,Memory Leaks,所以我将直截了当地说:我有一个函数,它将一些恰好是类的东西添加到另一个类中: tower->set_weapon(new NoWeapon()); set_武器是tower类中的一个简单方法,它将一个内部变量与其接收的新NoWeapon类相关联 virtual void set_weapon(Weapon* weapon){ weapon_ = weapon; }; 武器是指向武器类的指针,NoWeapon在层次上是武器的儿子。当一切都说了,做了,塔本身就清理一切: weapon_-&

所以我将直截了当地说:我有一个函数,它将一些恰好是类的东西添加到另一个类中:

tower->set_weapon(new NoWeapon());
set_武器是tower类中的一个简单方法,它将一个内部变量与其接收的新NoWeapon类相关联

virtual void set_weapon(Weapon* weapon){ weapon_ = weapon; };
武器是指向武器类的指针,NoWeapon在层次上是武器的儿子。当一切都说了,做了,塔本身就清理一切:

weapon_->Clean();
delete weapon_;
然而,我仍然有内存泄漏。我在VisualStudio 2013上使用vld,它在我提到的第一行上检测到内存泄漏

tower->set_weapon(new NoWeapon());
知道为什么会发生这种情况吗?我该如何解决

提前谢谢你

编辑:感谢YSC提供的解决方案。事实上,我因为没有初始化最初的武器指针而被泄露,但你的想法让我回到了正轨


至于独特的_ptr想法,我以前玩过,但这不是我想要的解决方案。无论如何,感谢您的帮助。

我们缺少上下文信息,但基本上如果两次调用Tower::set\u武器,则Tower::Fuel将被覆盖,内存将泄漏。建议:

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\u ptr:


我们缺少上下文信息,但基本上,如果两次调用Tower::set_武器,则Tower::武器会被覆盖,内存会泄漏。建议:

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\u ptr:


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

但是,如果调用Clean确实有一些原因,那么可以使用定制的deleter将所有这些封装在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);
    };
};

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

但是,如果调用Clean确实有一些原因,那么可以使用定制的deleter将所有这些封装在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);
    };
};


提供noWeapon和武器的定义。也许你不止一次调用set_武器,这里的代码忘记了在这种情况下处理以前的武器。根据你提供的代码量猜测一下,但是如果你两次调用set_武器,可能会发生这种情况;第一件武器永远不会被删除。我的ESP告诉我,你以后调用set_武器,用指向新武器的指针替换指针,从而泄漏原始的NoWeapon对象。你为什么使用原始指针?@DavidSchwartz,什么是ESP?提供noWeapon和武器的定义。也许你不止一次调用set_武器,这里的代码忘记了在这种情况下处理以前的武器。根据你提供的代码量猜测,但如果你两次调用set_武器,可能会发生这种情况;第一件武器永远不会被删除。我的ESP告诉我,你以后调用set_武器,用指向新武器的指针替换指针,从而泄漏原始的NoWeapon对象。为什么要使用原始指针?@DavidSchwartz,什么是ESP?并在方法中传递唯一的_ptr而不是原始指针!使用unique_ptr还可以避免复制问题规则三。除了使用unique_ptr之外,在析构函数中调用Clean可能会导致调用nullptr上的方法、在销毁武器时复制粘贴代码等问题大大减少-@理查德霍奇周五的晚上太残忍了!谢谢。并在方法中传递唯一的\u ptr而不是原始指针!使用unique_ptr还可以避免复制问题规则三。除了使用unique_ptr之外,在析构函数中调用Clean可能会导致调用nullptr上的方法、在销毁武器时复制粘贴代码等问题大大减少-@理查德霍奇周五的晚上太残忍了!谢谢