2013-06-28 35 views
1

所以,我試圖使用矢量與智能指針一起更容易與內存管理,以及...好吧,我有問題。 這就是(大大縮短)版本的我的代碼:vector加上unique_ptr到一個對象,內存不釋放?

bulletManager.h:

class BulletManager 
{ 
    public: 
     BulletManager(); 
     virtual ~BulletManager(); 

     void AddBullet(int type, double x, double y, double vx, double vy); 
     void EraseAllBullets(); 
    protected: 
    private: 
     std::vector<std::unique_ptr<Bullet>> bullets; 
}; 

bulletManager.cpp:

BulletManager::BulletManager() 
{ 
    bullets.reserve(50000); 
} 
void BulletManager::AddBullet(int type, double x, double y, double vx, double vy) 
{ 
    for(int i=0;i<1000;i++) bullets.push_back(std::unique_ptr<BasicBullet>(new BasicBullet(type, x, y, vx, vy))); 
} 
void BulletManager::EraseAllBullets() 
{ 
    bullets.clear(); 
} 

的BasicBullet類是抽象子彈類的子類。 爲了更容易地看到內存使用的變化,我使AddBullet函數生成了1000個對象,並且在項目符號類中放置了「char tab [10000]」。

現在,會發生什麼情況(根據任務管理器)是:

  • 調用AddBullet一次 - >內存使用量略有增加,
  • 後,調用EraseAllBullets - >內存使用情況根本不會滴!
  • 調用AddBullet幾次 - >顯着的內存使用增加
  • 之後調用EraseAllBullets - >大多數內存被釋放,但不是全部!

效果不是很大,似乎放慢了 - 程序以10MB的內存使用量開始,在使用這兩個函數一段時間後,每個向量清除內存使用量僅下降到15- 20MB。

我做錯了什麼?即使這種情況發生,如果我能夠釋放我分配的所有內存,我仍然會更喜歡。

回答

3

您不能依賴任務管理器來告訴您應用程序已分配/可用的內存量。釋放內存時,C++運行庫中的池可能會回收該內存,以供應用程序以後重用,而不是返回到操作系統。

+0

如果這是Windows內存管理的事情,而不是我的錯,我已經很高興。這件事在過去的幾個小時裏讓我頭痛。 因此,唯一可靠檢查實際泄漏的好方法是使用探查器? – Adrian17

+0

是DrMemory是一個不錯的選擇 –

2

你沒有做錯什麼,你只是有錯誤的假設。

你觀察可以來自兩個完全不同的事物的行爲:

  • std::vector::clear()只應該刪除包含於載體的對象,而不是實際釋放的載體本身的內存。作爲cppreference.com所說:「許多實現不會釋放clear()一個電話後分配的內存,有效地離開矢量不變capacity()。」通過使用std::vector<...>().swap(vectorToClear);,而不是clear()可以解決這一具體問題:該文件交換新的暫時的,空的矢量與你的,有效釋放你所使用的所有記憶。

  • C++的delete運算符不一定會將內存返回給系統。它只是釋放內存,以便它可以在new再次使用,同樣不需要系統重新獲得內存。該行爲沒有解決方法,它取決於您的運行時(即編譯器)。

+0

我不期待矢量釋放自己的內存 - 注意我已經使用了bullets.reserve(50000);在一開始。我只希望它能擺脫智能指針,因此他們會照顧刪除對象本身。 雖然我不知道第二部分。謝謝! – Adrian17

+0

從你發佈的代碼和解釋來看,你並不清楚你真正期望的是什麼(喲,我有一個艱難的一天),所以我想我還是會提到第一點以防萬一。 :)但是,第二點是非常重要的理解,以便你不會有任何意外。 – syam