使用std :: list <std :: string>时,std :: string会导致内存泄漏

Roc*_*ock 17 c++ string memory-leaks list

std::list<std::string>在我目前的项目中工作.但是有一个与此相关的内存泄漏.所以我分别测试了有问题的代码:

#include <iostream>
#include <string>
#include <list>

class Line {
public:
    Line();
    ~Line();
    std::string* mString;
};

Line::Line() {
    mString = new std::string("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
}

Line::~Line() {
    //mString->clear(); // should not be neccessary
    delete mString;
}

int main(int argc, char** argv)
{
    // no memory leak
    while (1==1) {
        std::string *test = new std::string("XXXXXXXXXXXXXXXXXXXXXXXX");
        delete test;
    }

    // LEAK!
    // This causes a memory overflow, because the string thats added
    // to the list is not deleted when the list is deleted.
    while (1==1) {
        std::list<std::string> *sl = new std::list<std::string>;
        std::string *s = new std::string("XXXXXXXXXXXXXXXXXXXXXXX");
        sl->push_back(*s);
        //sl->pop_back(); //doesn't delete the string?- just the pointer
        delete sl;
    }

    // LEAK!
    // Here the string IS deleted, but the memory does still fill up
    // but slower
    while (1==1) {
        std::list<Line> *sl = new std::list<Line>;
        Line *s = new Line();
        sl->push_back(*s);
        //sl->pop_back(); //does delete the Line-Element
        sl->clear();
        delete sl;
    }
    return 0;

    // this does not cause any noticable memory leak
    while (1==1) {
        std::list<int> *sl = new std::list<int>;
        int i = 0xFFFF;
        sl->push_back(i);
        sl->clear();
        delete sl;
    }
    return 0;

    // This does not cause any overflow or leak
    while (1==1) {
        int *i;
        i= new int [9999];
        delete[] i;
    }

}
Run Code Online (Sandbox Code Playgroud)

为什么我的字符串列表会导致内存泄漏?不应该删除列表导致在每个包含的字符串上调用析构函数?

grd*_*dev 30

在第一种情况下,list类不知道您分配了字符串new,并且无法删除它.特别是,该列表只包含您传入的字符串的副本.

同样,在第二种情况下,您永远不会释放线对象s,从而泄漏内存.删除内部字符串的原因是您没有正确实现复制构造函数.因此,如果您复制一个Line对象,它们都将引用相同的字符串指针,如果您尝试删除它们,则会遇到麻烦.


Mic*_*urr 13

Line类需要一个copy-ctor和一个正确处理字符串指针的赋值运算符.

或者,只需要一个std::string成员而不是指针,让string类处理内存(这就是它的用途).


Nik*_*sov 7

这是你的泄漏:

while (1==1) {
    std::list<Line> *sl = new std::list<Line>;
    Line *s = new Line();
    sl->push_back(*s);
    //sl->pop_back(); //does delete the Line-Element
    sl->clear();
    delete sl;
}
Run Code Online (Sandbox Code Playgroud)

STL集合按值存储元素,为其分配和释放空间.什么分配必须明确地释放.只需添加delete s循环结束即可.

如果必须存储指针,请考虑存储托管指针boost::shared_ptr,或者查看Boost指针容器库.

在第二种情况下,您根本不需要Line在堆上进行分配.只需将其更改为:

sl->push_back(Line());
Run Code Online (Sandbox Code Playgroud)

并且,正如其他人所指出的那样,确保Line在复制构造函数,复制赋值和析构函数中正确管理指针成员.