Утечка памяти в C++ в аргументе функции

Итак, я сразу перейду к сути: у меня есть функция, которая добавляет некоторые вещи (которые являются классом) в другой класс:

tower->set_weapon(new NoWeapon());

Set_weapon() - это простой метод в классе tower, который связывает внутреннюю переменную с этим новым классом NoWeapon, который он получает.

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

Weapon_ - указатель на класс Weapon, а NoWeapon - иерархически сын оружия. Когда все сказано и сделано, сама башня все очищает:

weapon_->Clean();
delete weapon_;

Тем не менее, я все еще получаю утечку памяти. Я использую vld на VisualStudio 2013, и он обнаруживает утечку памяти в первой строке, которую я упомянул

tower->set_weapon(new NoWeapon());

Любая идея, почему это происходит и как я могу обойти это?

Заранее спасибо!

РЕДАКТИРОВАТЬ: Спасибо YSC за решение. На самом деле я обнаружил утечку из-за того, что не инициализировал оригинальный указатель оружия, но ваши идеи вернули меня в нужное русло.

Что касается идей unique_ptr, я играл с ними раньше, но это было не то решение, которое я искал. В любом случае, спасибо за вашу помощь.

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);
    };
};

Примечание: ответ 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());
Другие вопросы по тегам