游戏对象工厂:修复内存泄漏

亲爱的,这将是艰难的:我创建了一个游戏对象工厂,生成我的愿望的对象。但是,我得到内存泄漏,我无法解决。 内存泄漏是通过返回new Object()生成的;在代码示例的底部。
static BaseObject * CreateObjectFunc()
{
    return new Object();
}
如何以及在何处删除指针?我写了bool ReleaseClassType()。尽管工厂运行良好,但ReleaseClassType()并不能解决内存泄漏问题。
bool ReleaseClassTypes()
{
    unsigned int nRecordCount = vFactories.size();
    for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
    {
        // if the object exists in the container and is valid, then render it
        if( vFactories[nLoop] != NULL) 
            delete vFactories[nLoop]();
    }
    return true;
}
在查看下面的代码之前,让我帮助您,我的CGameObjectFactory创建指向创建特定对象类型的函数的指针。指针存储在vFactories向量容器中。 我选择这种方式是因为我解析了一个对象映射文件。我有对象类型ID(整数值),我需要将它们转换为真实对象。因为我有超过100种不同的对象数据类型,所以我希望避免连续遍历很长的Switch()语句。 因此,为了创建一个对象,我通过CGameObjectFactory :: create()调用vFactories'['nEnumObjectTypeID']'()来调用生成所需对象的存储函数。 vFactories中相应函数的位置与nObjectTypeID相同,因此我可以使用索引来访问该函数。 所以问题仍然存在,如何进行垃圾收集并避免报告内存泄漏?
#ifndef GAMEOBJECTFACTORY_H_UNIPIXELS
#define GAMEOBJECTFACTORY_H_UNIPIXELS

//#include "MemoryManager.h"
#include <vector>


template <typename BaseObject>
class CGameObjectFactory
{
public:
    // cleanup and release registered object data types
    bool ReleaseClassTypes()
    {
        unsigned int nRecordCount = vFactories.size();
        for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
        {
            // if the object exists in the container and is valid, then render it
            if( vFactories[nLoop] != NULL) 
                delete vFactories[nLoop]();
        }
        return true;
    }

    // register new object data type
    template <typename Object>
    bool RegisterClassType(unsigned int nObjectIDParam )
    {
        if(vFactories.size() < nObjectIDParam) vFactories.resize(nObjectIDParam);

        vFactories[nObjectIDParam] = &CreateObjectFunc<Object>;
        return true;
    }


    // create new object by calling the pointer to the appropriate type function
    BaseObject* create(unsigned int nObjectIDParam) const
    {
        return vFactories[nObjectIDParam]();
    }


    // resize the vector array containing pointers to function calls
    bool resize(unsigned int nSizeParam)
    {
        vFactories.resize(nSizeParam);
        return true;
    }

private:
    //DECLARE_HEAP;

    template <typename Object>
    static BaseObject * CreateObjectFunc()
    {
        return new Object();
    }


    typedef BaseObject*(*factory)();
    std::vector<factory> vFactories;
};


//DEFINE_HEAP_T(CGameObjectFactory, "Game Object Factory");

#endif // GAMEOBJECTFACTORY_H_UNIPIXELS
    
已邀请:
您可以从使用std :: shared_ptr或std :: tr1 :: shared_ptr或boost :: shared_ptr开始,具体取决于您的编译器。 你会像这样使用它:
typedef std::shared_ptr<BaseObject> BaseObjectPtr;
static BaseObjectPtr CreateObjectFunc()
{
    return BaseObjectPtr(new Object());
}
您不需要释放创建的资源。当没有强引用指向它时,它们将执行自动引用计数并释放自己。 所以在你的第二个代码示例中:
#ifndef GAMEOBJECTFACTORY_H_UNIPIXELS
#define GAMEOBJECTFACTORY_H_UNIPIXELS

//#include "MemoryManager.h"
#include <vector>
#include <memory>

template <typename BaseObject>
class CGameObjectFactory
{
public:
    typedef std::shared_ptr<BaseObject> BaseObjectPtr;

    // cleanup and release registered object data types
    bool ReleaseClassTypes()
    {
        unsigned int nRecordCount = vFactories.size();
        for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
        {
            // if the object exists in the container and is valid, then render it
            //if( vFactories[nLoop] != NULL) 
            //    delete vFactories[nLoop]();
            // The above code would create something then immediately delete it.
            // You could keep a container of pointers to the objects you created
            // and loop through that instead, or use shared_ptr.
            // If you want to unregister the creator functions just NULL the pointer.
            vFactories[nLoop] = NULL;
        }
        return true;
    }

    // register new object data type
    template <typename Object>
    bool RegisterClassType(unsigned int nObjectIDParam )
    {
        if(vFactories.size() < nObjectIDParam) vFactories.resize(nObjectIDParam);

        // Store a pointer to the creation function
        vFactories[nObjectIDParam] = &CreateObjectFunc<Object>;
        return true;
    }


    // create new object by calling the pointer to the appropriate type function
    BaseObjectPtr create(unsigned int nObjectIDParam) const
    {
        return vFactories[nObjectIDParam]();
    }


    // resize the vector array containing pointers to function calls
    bool resize(unsigned int nSizeParam)
    {
        vFactories.resize(nSizeParam);
        return true;
    }

private:
    //DECLARE_HEAP;

    template <typename Object>
    static BaseObjectPtr CreateObjectFunc()
    {
        return BaseObjectPtr(new Object());
    }


    typedef BaseObjectPtr(*factory)();
    std::vector<factory> vFactories;
};


//DEFINE_HEAP_T(CGameObjectFactory, "Game Object Factory");

#endif // GAMEOBJECTFACTORY_H_UNIPIXELS
看看是否有帮助。     
  所以问题仍然是,如何   继续垃圾收集和   避免报告内存泄漏? 考虑使用
std::shared_ptr
或boost :: shared_ptr来管理你的
BaseObject
指针所有权。     
这一行:
delete vFactories[nLoop]();
调用new,然后立即删除该对象。它不会删除工厂创建的其他对象。您的泄漏检测工具是否为您提供未删除的分配的堆栈跟踪?如果没有,那就得到一个。     
ReleaseClassTypes
方法有缺陷:
delete vFactories[nLoop]();
基本上是说:
delete new Object();
您正在删除刚创建的对象,而不是通过调用
CGameObjectFactory::create()
创建的所有对象。 也就是说,您需要另一个向量来存储所有创建的对象,以便您可以一次性转储它们。     
正如其他人所说,看看
shared_ptr
的各种实现。 但是如果你真的想做你认为你的代码正在做的事情,你的创建和发布方法看起来应该更像这样(你还需要一个
vector
来存储创建的
BaseObject*
s[名为
vObjects
],因为你当前的代码只存储工厂,而不是创建的对象):
public:
BaseObject* create(unsigned int nObjectIDParam)
{
    BaseObject *obj = vFactories[nObjectIDParam]();
    //I'm assuming you have error handling/detection already in code that calls this create function

    vObjects.push_back(obj);
    return obj;
}

bool ReleaseClassTypes()
{
    for (typename vector<BaseObject*>::iterator iter = vObjects.begin(); iter != vObjects.end(); ++iter) {
        if (*iter) {
            delete *iter;
            *iter = NULL; //not strictly needed, but doesn't hurt
        }
    }
    vObjects.erase();
    return true; //you might as well just convert the return type to void
}
但是你应该编写一个析构函数来调用
ReleaseClassTypes
public:
~CGameObjectFactory() {
    ReleaseClassTypes();
}
并且与三条规则略有偏差,您可能希望将复制构造函数和赋值运算符设置为私有以禁止复制(或者您可以正确定义它们以获取新资源并释放旧资源,但我不是确定你需要复制工厂的原因)。
private:
CGameObjectFactory(const CGameObjectFactory& cgoFact) { }
CGameObjectFactory& operator=(const CGameObjectFactory& cgoFact) { return *this; }
    
建议的解决方案no1:使用内部向量生成指针   - 尚未工作 上述建议推荐两种解决方案。首先是创建另一个内部向量来记录由以下内容生成的所有指针:return new Object();
template <typename Object>
static BaseObject* CreateObjectFunc()
{   
     return new Object();
}
然后应该像在此函数中一样手动删除向量:
bool ReleaseClassTypes()
{
    unsigned int nRecordCount = vObjects.size();
    for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
    {
        if( vObjects[nLoop] != NULL) 
            delete vObjects[nLoop];
    }
    return true;
}
我根据建议做了,并且还厌倦了许多其他组合。但是,我得到编译错误:
d:sourcesatorisatorigameobjectfactory.h(48): error C2663: 'std::vector<_Ty>::push_back' : 2 overloads have no legal conversion for 'this' pointer
1>          with
1>          [
1>              _Ty=CGameObject *
1>          ]
1>          d:sourcesatorisatorigameobjectfactory.h(45) : while compiling class template member function 'CGameObject *CGameObjectFactory<BaseObject>::create(unsigned int) const'
1>          with
1>          [
1>              BaseObject=CGameObject
1>          ]
1>          d:sourcesatorisatoriresourcemanager.h(99) : see reference to class template instantiation 'CGameObjectFactory<BaseObject>' being compiled
1>          with
1>          [
1>              BaseObject=CGameObject
1>          ]
这是修改后的CGameObjectFactory,导致编译错误。关于现在问题在哪里的任何好的提示,好吗?
#ifndef GAMEOBJECTFACTORY_H_UNIPIXELS
#define GAMEOBJECTFACTORY_H_UNIPIXELS

#include "GameObject.h"
#include <vector>


template <typename BaseObject>
class CGameObjectFactory
{
public:
    //typedef std::shared_ptr<BaseObject> BaseObjectPtr;
    // cleanup and release registered object data types
    bool ReleaseClassTypes()
    {
        //unsigned int nRecordCount = vFactories.size();
        unsigned int nRecordCount = vObjects.size();
        for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
        {
            if( vObjects[nLoop] != NULL) 
                delete vObjects[nLoop];
        }
        return true;
    }


    // register new object data type
    template <typename Object>
    bool RegisterClassType(unsigned int nObjectIDParam )
    {
        if(vFactories.size() < nObjectIDParam) vFactories.resize(nObjectIDParam);
        vFactories[nObjectIDParam] = &CreateObjectFunc<Object>;

        return true;
    }


    // create new object by calling the pointer to the appropriate type function
    BaseObject* create(unsigned int nObjectIDParam) const
    {
        BaseObject* pObject = vFactories[nObjectIDParam]();
        vObjects.push_back(pObject);
        return pObject;
    }


    // resize the vector array containing pointers to function calls
    bool resize(unsigned int nSizeParam)
    {
        vFactories.resize(nSizeParam);
        return true;
    }

private:
    //DECLARE_HEAP;

    template <typename Object>
    static BaseObject* CreateObjectFunc()
    {   
        return new Object();
    }



    typedef  BaseObject* (*factory)();
    std::vector<factory> vFactories;
    std::vector<BaseObject*> vObjects;

};


//DEFINE_HEAP_T(CGameObjectFactory, "Game Object Factory");

#endif // GAMEOBJECTFACTORY_H_UNIPIXELS
    
建议的解决方案2:使用智能指针 - 尚未工作 上述建议推荐两种解决方案。第二种解决方案建议使用智能指针。我用std :: smart_ptr替换了键指针,如下面的代码所示:
#ifndef GAMEOBJECTFACTORY_H_UNIPIXELS
#define GAMEOBJECTFACTORY_H_UNIPIXELS

#include "GameObject.h"
#include <vector>
#include <memory>


template <typename BaseObject>
class CGameObjectFactory
{
public:
    typedef std::shared_ptr<BaseObject> BaseObjectPtr;

    // cleanup and release registered object data types
    bool ReleaseClassTypes()
    {
        unsigned int nRecordCount = vFactories.size();
        for (unsigned int nLoop = 0; nLoop < nRecordCount; nLoop++ )
        {
            // if the object exists in the container, then delete it
            if( vFactories[nLoop] != NULL) vFactories[nLoop] = NULL;
        }
        return true;
    }


    // register new object data type
    template <typename Object>
    bool RegisterClassType(unsigned int nObjectIDParam )
    {
        if(vFactories.size() < nObjectIDParam) vFactories.resize(nObjectIDParam);
        vFactories[nObjectIDParam] = &CreateObjectFunc<Object>;

        return true;
    }


    // create new object by calling the pointer to the appropriate type function
    BaseObjectPtr create(unsigned int nObjectIDParam) const
    {
        return vFactories[nObjectIDParam]();        
    }


    // resize the vector array containing pointers to function calls
    bool resize(unsigned int nSizeParam)
    {
        vFactories.resize(nSizeParam);
        return true;
    }

private:
    //DECLARE_HEAP;

    template <typename Object>
    static BaseObjectPtr CreateObjectFunc()
    {   
        return BaseObjectPtr(new Object());
    }



    typedef  BaseObjectPtr(*factory)();
    std::vector<factory> vFactories;

};


//DEFINE_HEAP_T(CGameObjectFactory, "Game Object Factory");

#endif // GAMEOBJECTFACTORY_H_UNIPIXELS
代码编译得很好。但是,我得到错误说:   调试错误!      HEAP CORRUPTION DETECTED:正常后   块(#949)位于0x04DC7E68。      CRT检测到该应用程序   在堆结束后写入内存   缓冲。      内存分配在:filepath到CGameObjectFactory中的行:return   BaseObjectPtr(new Object()); * 我在弹出窗口中有三个选项:Abort,Retry,Ignore 如果我重复按Ignore,分配的游戏指针的向量容器显然会被删除,因为,我最终会没有内存泄漏。另一方面,如果我按Abort,我最终会再次出现内存泄漏。 知道这可能表明什么吗?我猜,我的代码中没有任何专业,所以我完全不理解这种行为。     

要回复问题请先登录注册