Утечка памяти в 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());