【问题标题】:ptr_vector - _CrtDumpMemoryLeaks() - memory leaks even though destructor is calledptr_vector - _CrtDumpMemoryLeaks() - 即使调用了析构函数,内存泄漏
【发布时间】:2010-07-13 21:02:17
【问题描述】:

我正在开发一个游戏引擎,在之前的问题中,有人建议我开始使用 boost::ptr_vector 来维护指针列表。

基本思想是有几个State,每个State都有一个SceneGraph。每个状态都有几个初始化的资源,然后填充自己的场景图。 SceneGraph 有一个 boost::ptr_vector,它将资源指针塞入其中。

以下是相关代码:

在 TestState 中创建资源并添加到 SceneGraph

backgroundImage = new DEBUG_NEW Fenris::Node2D::Image(std::string("backgroundImage"), std::string("../media/img/background.jpg"));
sceneGraph->addNode(backgroundImage, Fenris::Core::STRATUM_BACK);

场景图

boost::ptr_vector<SceneGraphNode> backStratumList;
// The add() method
void addNode(SceneGraphNode *pNode, STRATUM_TYPE stratumType) { switch(stratumType) { case STRATUM_BACK: backStratumList.push_back(pNode); break; case STRATUM_NORMAL: normalStratumList.push_back(pNode); break; case STRATUM_FOREGROUND: foregroundStratumList.push_back(pNode); break; } }

用相关行编辑 main.cpp

PlatformGame::State::TestState *testState = new DEBUG_NEW PlatformGame::State::TestState(std::string("testState"));
// Clean up the previously registered state (deletes its sceneGraph -- verified that the destructor is in fact called via debugger) delete testState;
// Dump memleak report if we're running in debug mode #ifdef _DEBUG _CrtDumpMemoryLeaks(); #endif

我正在使用 _CrtDumpMemoryLeaks() 来输出内存泄漏日志报告。日志报告告诉我有内存泄漏;

检测到内存泄漏! 倾倒对象 -> {174} 0x00A56630 处的普通块,32 字节长。 数据:<..> 2E 2E 2F 6D 65 64 69 61 2F 69 6D 67 2F 62 61 63 {173} 0x00A565A0 处的普通块,8 字节长。 数据:A8 63 A5 00 00 00 00 00 对象转储完成。

_CrtDumpMemoryLeaks() 是否在 boost::ptr_vector 上遇到问题,还是我做错了什么?调试器告诉我 State 确实调用了它的析构函数(它有;delete sceneGraph),我还验证了 SceneGraph 的析构函数也被调用了。

非常感谢任何帮助,我希望看到一个空的内存泄漏报告 :-)

【问题讨论】:

标签: c++ boost memory-leaks ptr-vector


【解决方案1】:

它看起来肯定不像您正在泄漏的向量。请注意,字符串是可读的,这至少是一个提示。

如果你可以得到稳定的大括号之间的数字(“{173}”),那么你可以在分配内存时得到一个断点。把它放在你的 main() 函数中:

_crtBreakAlloc = 173;

如有必要,请使用#include &lt;crtdbg.h&gt;。重复 174 以找到另一个。

【讨论】:

  • +1 表示 breakAlloc 提示,但实际上可能无助于查明泄漏的原因。
  • 不,它是无与伦比的,它在发生分配的源代码位置中断。如果数字一致。没那么难,程序再次运行时必须按照相同的顺序分配内存。
  • 我知道我没有泄漏向量,但如果我没有误解 boost::ptr_vector,ptr_vector 将拥有添加到向量的指针的所有权,并在 ptr_vector 被破坏时删除它们包含 ptr_vector 的类。我一定会尝试使用 breakAlloc。
  • @Hans:是的,但实际的修复可能在其他地方(例如某些包含“罪魁祸首”类的类中缺少删除)。这就是我上面所说的意思。
  • @John:我很好奇。你找出泄漏的原因了吗?
【解决方案2】:

好吧,您的代码可能是 100% 合法的。我有同样的问题,但使用 Valgrind 并且还使用 boost::ptr_vector。以下是用于测试目的的原型:

#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/shared_ptr.hpp>
#include <map>

using namespace std;
class Object
{
    public:
        Object(){ abc=1;};
        ~Object(){cout<<"destructor Object"<<endl;};
        int abc;
};

class test : public boost::ptr_vector<Object>
{
    public:

        test(){}
        virtual ~test(){cout<<"destructor test"<<endl;}
        void add(){
            PARENT::push_back(new Object());
        }
    protected:

        typedef boost::ptr_vector<Object> PARENT;
        test(const test& abc);
};

    typedef boost::shared_ptr<test> shared_type;
    typedef std::map< int, std::pair<shared_type, shared_type> > maptype;

    maptype::mapped_type get()
    {
        boost::shared_ptr<test> testObj(new test);
        boost::shared_ptr<test> testObj2(new test);

        test &ref= *(testObj.get());
        test &ref2= *(testObj2.get());

        ref.reserve(4);
        ref.add();
        ref.add();
        ref.add();
        ref.add();
        ref2.reserve(4);
        ref2.add();
        return maptype::mapped_type(testObj,testObj2);
    }

int main() {
    std::map< int, std::pair<shared_type, shared_type> > mapped;
    mapped.insert(maptype::value_type(1,get()));

    return 0;
}

我在这里测试了一些内部结构,所以不关心设计。 输出是:

destructor test
destructor Object
destructor test
destructor Object
destructor Object
destructor Object
destructor Object

Valgrind 也可以在这里抱怨,我想这是由于 ptr_vector

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2013-12-06
    • 2013-11-28
    • 2012-09-02
    • 1970-01-01
    相关资源
    最近更新 更多