2

我遇到了 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 个内存泄漏仍然存在。

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

4

3 回答 3

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
于 2012-12-28T23:55:24.620 回答
1

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

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

在你的主要开始

泄漏将在程序退出时检查,现在您在对象仍在堆栈上时检查它们,因此您没有泄漏。

如果您使用虚拟方法,则应该添加虚拟析构函数,尽管在您的情况下它不会导致内存泄漏,但如果您的列表将包含动态分配的对象,那么 AbstractObject 中的虚拟析构函数将是强制性的。

至于你的问题:

"//我这里也需要"virtual"关键字吗?"

是的,只要您的 list<> 是基类指针类型

于 2012-12-29T00:00:17.180 回答
0

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

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

按照建议将包含std::list在单独的范围内{ ... }或调用_CrtDumpMemoryLeaks全局对象的析构函数应该不会显示任何泄漏。

于 2012-12-29T00:01:31.040 回答