c++ shared_ptr 继承内存问题 "Bad deallocation"
c++ shared_ptr inheritance memory problems "Bad deallocation"
我尝试按照给定的说明解决大学问题。代码可以编译,但会产生有关内存的警告。这是代码的关键:
#include <iostream>
#include <vector>
#include <memory>
using std::vector;
using std::shared_ptr;
using std::make_shared;
class ApsClass {
protected :
double goose;
public :
virtual ~ApsClass() {}
virtual shared_ptr<ApsClass> clone() const = 0;
double GetGoose() const { return goose; }
};
class DerivedClass : public ApsClass {
public :
~DerivedClass() {} // Warning here*
DerivedClass(double goose) { DerivedClass::goose = goose; }
shared_ptr<ApsClass> clone() const override;
};
shared_ptr<ApsClass> DerivedClass::clone() const {
return make_shared<DerivedClass>(goose);
}
class Storage {
vector<shared_ptr<ApsClass>> geese;
public :
Storage() {}
ApsClass *AddApsClass(ApsClass *pok);
void DelApsClass(ApsClass *pok);
};
ApsClass *Storage::AddApsClass(ApsClass *pok)
{
// The instructions stated that the object pointed at by pok has no
// other pointers pointing at it, and should now be "owned" by geese
geese.push_back(shared_ptr<ApsClass>(pok));
return pok;
}
void Storage::DelApsClass(ApsClass *pok)
{
for (int i = 0; i < geese.size(); i++)
if (geese[i] == shared_ptr<ApsClass>(pok)) {
geese.erase(geese.begin() + i);
break;
}
}
int main ()
{
Storage Foo;
ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
return 0;
}
main() 基本上是来自自动测试的代码,我应该修改程序的其余部分以使 main() 正常工作。
警告是在派生的 class* 的析构函数定义中报告的,当翻译成英文时它只是说 "Bad deallocation"。我的问题是:代码中哪里以及为什么会出现这个问题?
我删除的代码对内存分配没有影响(我希望如此),并且是通过自动测试进行测试的,我没有多少访问权限。一项测试报告了以下内容:
Invalid read of size 8 ...
Address 0x51f0090 is 0 bytes inside a block of size 56 free'd
和
==10216== Jump to the invalid address stated on the next line
==10216== at 0x0: ???
Address 0x0 is not stack'd, malloc'd or (recently) free'd
和
==10216== Process terminating with default action of signal 11 (SIGSEGV)
==10216== Bad permissions for mapped region at address 0x0
==10216== at 0x0: ???
如果需要更多细节,我可以把一些原始代码放在这里。
每次执行 shared_ptr<ApsClass>(pok)
时,您都在创建一个新的 shared_ptr
,它不知道指向同一对象的所有其他 shared_ptr
。所以当这个 shared_ptr
被销毁时,它会销毁对象。
但是因为你做了几次(在你的情况下是两次)对象被破坏了不止一次。
只有 shared_ptr
从普通指针创建的有这个问题。从另一个 shared_ptr
创建一个 shared_ptr
没问题。
你应该创建一个 shared_ptr
一次 - 改变这个
ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
对此:
shared_ptr<ApsClass> aps(new DerivedClass(0.5));
shared_ptr<ApsClass> s = Foo.AddApsClass(aps);
Foo.DelApsClass(s);
并将 ApsClass *
更改为 shared_ptr<ApsClass>
其他所有地方。
我尝试按照给定的说明解决大学问题。代码可以编译,但会产生有关内存的警告。这是代码的关键:
#include <iostream>
#include <vector>
#include <memory>
using std::vector;
using std::shared_ptr;
using std::make_shared;
class ApsClass {
protected :
double goose;
public :
virtual ~ApsClass() {}
virtual shared_ptr<ApsClass> clone() const = 0;
double GetGoose() const { return goose; }
};
class DerivedClass : public ApsClass {
public :
~DerivedClass() {} // Warning here*
DerivedClass(double goose) { DerivedClass::goose = goose; }
shared_ptr<ApsClass> clone() const override;
};
shared_ptr<ApsClass> DerivedClass::clone() const {
return make_shared<DerivedClass>(goose);
}
class Storage {
vector<shared_ptr<ApsClass>> geese;
public :
Storage() {}
ApsClass *AddApsClass(ApsClass *pok);
void DelApsClass(ApsClass *pok);
};
ApsClass *Storage::AddApsClass(ApsClass *pok)
{
// The instructions stated that the object pointed at by pok has no
// other pointers pointing at it, and should now be "owned" by geese
geese.push_back(shared_ptr<ApsClass>(pok));
return pok;
}
void Storage::DelApsClass(ApsClass *pok)
{
for (int i = 0; i < geese.size(); i++)
if (geese[i] == shared_ptr<ApsClass>(pok)) {
geese.erase(geese.begin() + i);
break;
}
}
int main ()
{
Storage Foo;
ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
return 0;
}
main() 基本上是来自自动测试的代码,我应该修改程序的其余部分以使 main() 正常工作。
警告是在派生的 class* 的析构函数定义中报告的,当翻译成英文时它只是说 "Bad deallocation"。我的问题是:代码中哪里以及为什么会出现这个问题?
我删除的代码对内存分配没有影响(我希望如此),并且是通过自动测试进行测试的,我没有多少访问权限。一项测试报告了以下内容:
Invalid read of size 8 ...
Address 0x51f0090 is 0 bytes inside a block of size 56 free'd
和
==10216== Jump to the invalid address stated on the next line
==10216== at 0x0: ???
Address 0x0 is not stack'd, malloc'd or (recently) free'd
和
==10216== Process terminating with default action of signal 11 (SIGSEGV)
==10216== Bad permissions for mapped region at address 0x0
==10216== at 0x0: ???
如果需要更多细节,我可以把一些原始代码放在这里。
每次执行 shared_ptr<ApsClass>(pok)
时,您都在创建一个新的 shared_ptr
,它不知道指向同一对象的所有其他 shared_ptr
。所以当这个 shared_ptr
被销毁时,它会销毁对象。
但是因为你做了几次(在你的情况下是两次)对象被破坏了不止一次。
只有 shared_ptr
从普通指针创建的有这个问题。从另一个 shared_ptr
创建一个 shared_ptr
没问题。
你应该创建一个 shared_ptr
一次 - 改变这个
ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
对此:
shared_ptr<ApsClass> aps(new DerivedClass(0.5));
shared_ptr<ApsClass> s = Foo.AddApsClass(aps);
Foo.DelApsClass(s);
并将 ApsClass *
更改为 shared_ptr<ApsClass>
其他所有地方。