2016-08-04 60 views
-11
bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName) 
{ 
    DWORD dwElements; 

    TMobTable *pTable = (TMobTable *) zObj.GetBuffer(); 

    for(DWORD i = 0; i < dwElements; ++i, ++pTable) 
    { 
     TMobTable *pNonPlayerData = new TMobTable; 
     memcpy(pNonPlayerData, pTable, sizeof(TMobTable)); 
     m_NonPlayerDataMap.insert(TNonPlayerDataMap::value_type(pNonPlayerData->dwVnum, pNonPlayerData)); 
    } 

    return true; 
} 

我的問題是:我做錯了什麼?這泄漏了很多內存。每次調用此函數後,應用程序使用量增加10MB。動態分配泄漏內存?

+5

任何時候你有一個'新'你需要'刪除'。我沒有看到你使用'delete'。 – NathanOliver

+2

不要嘗試自己使用'new'和'delete'。這可以防止你遭受很多麻煩和悲傷。 –

+2

如果map :: insert失敗,該代碼將泄漏內存。如果您要使用map來在地圖中存儲指向動態內存的指針,並且假設'map.insert'正常工作,切勿編寫這樣的代碼。如果地圖中的鍵值已經存在,那麼你有泄漏。 – PaulMcKenzie

回答

3

問題不在於此功能。問題出在您處理m_NonPlayerDataMap的方式。該功能將某些對象的所有權轉移給該地圖,並且這個地圖對它們的責任是delete。我敢打賭它沒有。

順便說一句,爲了避免這種問題只是不要這樣做。除非你真的需要,否則不要使用new。相反,使地圖的值爲而不是指針圖。如果你找不到任何方法來實現這一點,至少使用智能指針而不是原始指針。

+3

比這更糟糕。如果'map :: insert'由於地圖中已經存在的密鑰而失敗,泄漏是有保證的。 – PaulMcKenzie

1

使用智能指針包裝來處理內存管理你的,例如:

如果使用一個版本早於C++ 11:

#include <memory> 

// std::auto_ptr is not container-safe! 
typedef std::map<DWORD, TMobTable*> TNonPlayerDataMap; 
TNonPlayerDataMap m_NonPlayerDataMap; 

... 

bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName) 
{ 
    DWORD dwElements = ...; 
    ... 

    // I'm assuming this just returns a pointer to an existing memory 
    // buffer and is not actually allocating a new buffer. If it is, 
    // you need to free it when you are done copying it... 
    // 
    TMobTable *pTable = (TMobTable *) zObj.GetBuffer(); 

    for(DWORD i = 0; i < dwElements; ++i, ++pTable) 
    { 
     std::auto_ptr<TMobTable> pNonPlayerData(new TMobTable); 

     // don't use memcpy! better would be to give TMobTable a copy constructor instead... 
     // std::auto_ptr<TMobTable> pNonPlayerData(new TMobTable(*pTable)); 
     // 
     *pNonPlayerData = *pTable; 

     // if successful, release local ownership of the object. 
     // if failed, ownership will remain here and free the object when the auto_ptr goes out of scope. 
     // 
     if (m_NonPlayerDataMap.insert(std::make_pair(pNonPlayerData->dwVnum, pNonPlayerData.get())).second) 
      pNonPlayerData.release(); 
    } 

    return true; 
} 

另外,如果你使用的是C++ 11或後來:

#include <memory> 

// std::unique_ptr is container-safe! 
typedef std::map<DWORD, std::unique_ptr<TMobTable>> TNonPlayerDataMap; 
TNonPlayerDataMap m_NonPlayerDataMap; 

... 

bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName) 
{ 
    DWORD dwElements = ...; 
    ... 

    // I'm assuming this just returns a pointer to an existing memory 
    // buffer and is not actually allocating a new buffer. If it is, 
    // you need to free it when you are done copying it... 
    // 
    TMobTable *pTable = (TMobTable *) zObj.GetBuffer(); 

    for(DWORD i = 0; i < dwElements; ++i, ++pTable) 
    { 
     std::unique_ptr<TMobTable> pNonPlayerData(new TMobTable); 
     // 
     // or, if using C++14 or later: 
     // std::unique_ptr<TMobTable> pNonPlayerData = std::make_unique<TMobTable>(); 

     // don't use memcpy! better would be to give TMobTable a copy constructor instead... 
     // std::unique_ptr<TMobTable> pNonPlayerData(new TMobTable(*pTable)); 
     // std::unique_ptr<TMobTable> pNonPlayerData = std::make_unique<TMobTable>(*pTable); 
     // 
     *pNonPlayerData = *pTable; 

     // if successful, ownership of the object is transferred into the map. 
     // if failed, ownership will remain here and free the object when the unique_ptr goes out of scope. 
     // 
     m_NonPlayerDataMap.insert(std::make_pair(pNonPlayerData->dwVnum, std::move(pNonPlayerData))); 
    } 

    return true; 
}