std :: list内存泄漏与接口

时间:2012-12-28 23:52:55

标签: c++ memory-leaks interface virtual abstract-class

我遇到std :: list和内存泄漏问题:

class AbstractObject
{
    public:
        virtual void Say() = 0;
}
class RealObject : public AbstractObject
{
    public:
        virtual void Say() { cout << "Real Obj Says..." << endl; } //Do I need the "virtual" keyword here too?
}
class AnotherRealObject : public AbstractObject
{
    public:
        virtual void Say() { cout << "Another Real Obj Says..." << endl; } //Do I need the "virtual" keyword here too?
}
class PackOfObjects
{
    public:
        std::list<AbstractObject*> objects; //list of pointers because it doesn't let me create a list of an abstract class
        void Say()
        {
            for(std::list<AbstractObject*>::iterator obj = objects.begin(); obj != objects.end(); obj++)
            {
                (*obj)->Say();
            }
        }
}
int _tmain(int argc, _TCHAR* argv[])
{
    PackOfObjs myObjs;

    RealObject objA;
    myObjs.objects.push_back(&objA); //This adds 1 memory leak
    AnotherRealObject objB;
    myObjs.objects.push_back(&objB); //This adds another 1 memory leak

    _gettch();
    _CrtDumpMemoryLeaks();
    return 0;
}

只是声明了PackOfObjs我已经有2个内存泄漏,如果我删除了std :: list它们会消失,并且对于我添加到列表中的每个地址它们会增加1。 我尝试清除列表和一些删除清除之前指向的所有obj的代码,但至少有2个内存泄漏仍然存在。

由于我没有使用任何 new (甚至不添加我添加的元素),我猜测列表本身会创建一些变量并且不删除它们,我该如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

_CrtDumpMemoryLeaks()运行时,main内分配的所有对象仍然存在。您过早地致电_CrtDumpMemoryLeaks()。相反,试试这个:

int _tmain(int argc, _TCHAR* argv[])
{
    {
        PackOfObjs myObjs;

        RealObject objA;
        myObjs.objects.push_back(&objA); //This adds 1 memory leak
        AnotherRealObject objB;
        myObjs.objects.push_back(&objB); //This adds another 1 memory leak

        // <- all memory used by the list is freed here
    }
    _gettch();
    _CrtDumpMemoryLeaks();
    return 0;
}

我似乎记得调用_CrtDumpMemoryLeaks的推荐方法是在全局对象的析构函数中。对于其他全局对象来说,这可能还为时过早,但至少在main内创建的所有对象都已经被破坏了。

struct memory_leak_dumper
{
    ~memory_leak_dumper(){ _CrtDumpMemoryLeaks(); }
};
memory_leak_dumper _dumper; // this is a global object

答案 1 :(得分:1)

要检查内存泄漏,您应该使用:

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

在你的主要开始

泄漏将在程序出口处检查,现在你在对象仍在堆栈时检查它们,所以你没有泄漏。

如果你使用虚方法,你应该添加虚析构函数,虽然在你的情况下它不会导致内存泄漏,但如果你的列表包含动态分配的对象,那么AbstractObject中的虚析构函数是必需的。

关于你的问题:

“//我在这里也需要”虚拟“关键字吗?”

是的,只要您的列表&lt;&gt;是基类指针类型

答案 2 :(得分:0)

要扩展K-ballo's answer,技术上_CrtDumpMemoryLeaks检查堆上的对象。虽然你没有在堆上直接分配任何东西,但是std::list(以及为此事件动态管理内存的所有容器)都可以 - 否则动态大小将不是一个选项。

所以不,技术上没有泄漏,但在你调用_CrtDumpMemoryLeaks时,动态分配的内存仍在使用中,尚未被释放(尚未)。

std::list封装在一个单独的范围{ ... }中,或者在建议的全局对象的析构函数中调用_CrtDumpMemoryLeaks应该显示没有泄漏。