动态分配泄漏内存?
Posted
技术标签:
【中文标题】动态分配泄漏内存?【英文标题】:Dynamic allocation leaks memory? 【发布时间】:2016-12-11 00:03:58 【问题描述】: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。
【问题讨论】:
任何时候你有一个new
,你需要一个delete
。我没有看到你使用delete
。
不要尝试自己使用new
和delete
。这样可以避免你遇到很多麻烦和悲伤。
如果map::insert
失败,此代码将泄漏内存。如果您要使用map
在映射中存储指向动态内存的指针,并且假设map.insert
可以工作,则永远不要编写这样的代码。如果映射中的键值已经存在,那么你就有了泄漏。
dwElements
在哪里初始化?
不要破坏你自己的问题。这是不允许的。
【参考方案1】:
问题不在于这个函数。问题在于您处理m_NonPlayerDataMap
的方式。此函数将某些对象的所有权转移到该映射,当映射完成时,该映射对delete
负责。我敢打赌不会。
顺便说一句,为了避免这种问题不要这样做。除非你真的需要,否则不要使用new
。相反,使地图成为值的地图,而不是指针的地图。如果你想不出任何方法来实现这一点,至少使用智能指针而不是原始指针。
【讨论】:
比这更糟糕。如果map::insert
由于映射中已经存在的密钥而失败,则保证泄漏。【参考方案2】:
使用智能指针包装器为您处理内存管理,例如:
如果使用 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;
【讨论】:
以上是关于动态分配泄漏内存?的主要内容,如果未能解决你的问题,请参考以下文章
Dynamically allocated memory 动态分配内存mallocMemory leaks 内存泄漏