每次我想在存储类中向std :: map添加元素时,我都会收到错误“未释放指针被释放”。我在构造函数和析构函数中添加了一些“couts”来调试,输出是:
新 德尔 德尔
所以似乎析构函数在main()和添加新元素时被调用两次。
以下是代码:
Container.h
#include <map>
#include "Element.h"
using std::map;
class Container
{
private:
map<string, Element> storage;
public:
Container();
~Container();
void add(Element e);
void remove(string s);
};
Container.cpp
#include "Container.h"
Container::Container()
{
}
Container::~Container()
{
}
void Container::add(Element e)
{
storage.insert(pair<string, Element>(e.getS(), e)); // CRASH
}
void Container::remove(string s)
{
storage.erase(s);
}
element.h展开
#include <iostream>
#include <string>
using namespace std;
class Element
{
private:
string *s;
public:
Element();
Element(string s);
~Element();
string getS();
};
Element.cpp
#include <iostream>
#include "Element.h"
Element::Element()
{
s = new string("std cons");
std::cout << "new" << std::endl;
}
Element::Element(string s2)
{
s = new string(s2);
std::cout << "new" << std::endl;
}
Element::~Element()
{
std::cout << "del" << std::endl;
delete s;
}
string Element::getS()
{
return *this->s;
}
的main.cpp
#include <iostream>
#include "Element.h"
#include "Container.h"
int main(int argc, const char * argv[])
{
Element e("l");
Container c;
c.add(e);
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
这里的问题是Element
上有默认的复制构造函数。它本质上是一个不分配新内存的字段的成员副本。
Element e1("l");
Element e2(e1);
此时有2 Element
个值,但E::s
的内存只分配了一次。但是,每个Element
值都会尝试free
内存,因此最终会出现双free
错误。
要解决此问题,您需要确保Element
的每个副本都有自己的内存副本来管理
Element::Element(Element& other)
{
s = new string(other.s);
}
或者更好的是,按价值
按住Element:s
class Element
{
string s;
...
};
答案 1 :(得分:1)
错误的原因是您既没有为类Element定义复制构造函数也没有定义复制赋值运算符。
在这种情况下由编译器隐式定义的相应函数只需将指针复制到字符串即可。
结果两个对象指向相同的字符串。删除一个对象时,第二个对象的指针无效。当它被删除时,你会得到错误。
此外,无需定义指向std :: string的类型指针的数据成员。如果您将此数据成员定义为
,则会简单得多class Element
{
private:
string s;
public:
Element();
Element( const string &s );
~Element();
string getS() const;
};
在这种情况下,定义可能看起来像
#include <iostream>
#include "Element.h"
Element::Element() : s( "std cons" )
{
std::cout << "new" << std::endl;
}
Element::Element( const string &s2 ) : s( s2 )
{
std::cout << "new" << std::endl;
}
Element::~Element()
{
std::cout << "del" << std::endl;
}
string Element::getS() const
{
return s;
}