2015-12-11 71 views
1

所以我將直接切入正題:我是加入一些東西(這恰好是一個類)到另一個類的函數:C++內存泄漏的函數參數

tower->set_weapon(new NoWeapon()); 

的set_weapon()是塔類中的一個簡單方法,它將一個內部變量與它接收的這個新的NoWeapon類相關聯。

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

weapon_是Weapon類的指針,NoWeapon是武器的子級。當一切都說完了,塔本身清理一切:

weapon_->Clean(); 
delete weapon_; 

但是,我仍然得到內存泄漏。即時通訊使用的VisualStudio上2013 VLD,它檢測到我提到

tower->set_weapon(new NoWeapon()); 

任何想法,爲什麼這種情況正在發生和我怎麼能解決它的第一行中的內存泄漏?

預先感謝您!

編輯:感謝YSC的解決方案。事實上,我沒有初始化原始武器指針,但是你的想法讓我回到了正軌。

至於unique_ptr的想法,我以前玩過,但它不是我尋找的解決方案。還是要謝謝你的幫助。

+2

爲noWeapon和武器提供的定義。 – ForeverStudent

+1

也許你不止一次地調用了set_weapon(),這裏的代碼忘了爲這種情況處置先前的武器。 – nos

+0

只是猜測給定的代碼量,但如果你兩次調用'set_weapon',就會發生這種情況;第一件武器永遠不會被刪除。 – dfan

回答

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

並在方法中傳遞unique_ptr而不是原始指針! –

+0

@RichardHodges修復 – YSC

+2

使用'unique_ptr'也可以避免複製問題(規則三)。 –

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