动态分配泄漏内存?

时间:2016-08-04 18:13:04

标签: c++ memory-leaks

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。

2 个答案:

答案 0 :(得分:3)

问题不在此功能中。问题在于您处理m_NonPlayerDataMap的方式。此功能将某些对象的所有权转移到该地图,并且当它完成时,它将delete的责任映射到它们。我打赌它没有。

顺便说一句,要避免这种问题,就是不要这样做。除非你真的需要,否则不要使用new。相反,使地图成为的地图,而不是指针地图。如果你无法找到实现这一目标的任何方法,至少使用智能指针而不是原始指针。

答案 1 :(得分: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;
}