3

我之前在某处读过向量会导致内存泄漏,具体取决于它们的使用方式,但我想问一下以确保:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

int main()
{
    vector<somePtr*> listPtrs;

    return 0;
    //Detects memory leaks
}

这并没有检测到任何东西:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

int main()
{
    {
        vector<somePtr*> listPtrs;
    }

    return 0;
    //No memory leaks detected
}

在清除指针之前,正在从向量中删除对象。我想我记得读过向量和列表以及其他 std 容器在它们所在的块之后自动删除,所以在示例 1 中我得到内存泄漏,因为在块结束之前调用了内存泄漏函数,所以向量仍然活着并导致它。

不过我不确定,自从我想我读到这篇文章已经有一段时间了,我只能找到关于对象没有被删除的问题,只是指针被删除了。

这是真的?如果我使用包含向量和列表的全局类,我会出现内存泄漏吗?

4

2 回答 2

11

您调用的时间点_CrtDumpMemoryLeaks很重要,因为所有使用的内存可能尚未释放。例如在下面的示例中,如果您在超出范围_CrtDumpMemoryLeaks()之前调用它已分配的任何内存都将包含在泄漏内存列表中。listPtrs

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <vector>

int main()
{
    std::vector<struct Foo*> listPtrs;

    _CrtDumpMemoryLeaks();

    return 0;
}

在下面的示例中listPtrs,在调用之前超出范围,_CrtDumpMemoryLeaks因此它分配的任何内存都将被释放,并且不会在泄漏的内存块中列出。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <vector>

int main()
{
    {
        std::vector<struct Foo*> listPtrs;
    }

    _CrtDumpMemoryLeaks();

    return 0;
}

同样,如果您在 main 返回_CrtDumpMemoryLeaks std::vector调用,则应释放分配的任何资源。这再次是因为listPtrs现在已经超出范围并且std::vector已经调用了析构函数。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <vector>

// Call _CrtDumpMemoryLeaks after main has returned and before program terminates.
struct AtExit
{
    ~AtExit() { _CrtDumpMemoryLeaks(); }
} doAtExit;

int main()
{
    std::vector<struct Foo*> listPtrs;

    return 0;
}

我强烈建议使用智能指针而不是裸指针。它让它们在冬天保持温暖,您不必担心使用delete.

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <vector>
#include <memory>

// Call _CrtDumpMemoryLeaks after main has returned and before program terminates.
struct AtExit
{
    ~AtExit() { _CrtDumpMemoryLeaks(); }
} doAtExit;

int main()
{
    std::vector<std::unique_ptr<struct Foo*>> listPtrs;

    return 0;
}
于 2013-08-05T21:13:43.450 回答
1

在这两段代码中,您已经vector<>在堆栈上分配了您的代码。因此,向量的析构函数将在超出范围时被调用。我不知道您使用的是什么检漏仪,但如果它在主出口之前检查泄漏,它可能确实检测到泄漏,但它并不是真正的泄漏。

您遇到内存泄漏问题的地方是std::vector析构函数不会调用delete向量中的项目,尽管它会调用它们的析构函数。因此vector<int>vector<MyClass>很好,因为向量包含实际对象并将其称为析构函数。另一方面,如果您有vector<MyClass*>,则需要小心;删除向量不会MyClass释放与其指向的对象关联的内存。

于 2013-08-05T21:06:52.840 回答