简体   繁体   English

c ++ shared_ptr继承内存问题“错误的重新分配”

[英]c++ shared_ptr inheritance memory problems “Bad deallocation”

I tried solving a university problem by following the given instructions. 我尝试按照给定的说明解决大学问题。 The code compiles but it produces a warning about memory. 代码可以编译,但是会产生有关内存的警告。 Here is the crux of the code: 这是代码的症结所在:

#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() is basically the code from an autotest, I am supposed to modify the rest of the program to make main() work properly. main()基本上是自动测试的代码,我应该修改程序的其余部分以使main()正常工作。
The warning is reported at the destructor definition of the derived class*, it just says "Bad deallocation" when translated to English. 警告是在派生类*的析构函数定义中报告的,当翻译成英语时,它只会显示“错误的释放”。 My question is: Where and why does this problem occur in the code? 我的问题是:代码中何处以及为什么会出现此问题?

The code I've cut out has no effect on the memory allocation (I hope), and is tested via autotesting which i don't have much access to. 我切出的代码对内存分配没有影响(我希望如此),并通过自动测试进行了测试,而我对此没有太多访问权。 One test reports the following among the others: 其中一项测试报告了以下内容:

Invalid read of size 8 ...  
Address 0x51f0090 is 0 bytes inside a block of size 56 free'd 

and

==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

and

==10216== Process terminating with default action of signal 11 (SIGSEGV)
==10216== Bad permissions for mapped region at address 0x0
==10216== at 0x0: ???

If further details are needed I can put some of the original code here. 如果需要更多详细信息,我可以在此处放置一些原始代码。

Every time you do shared_ptr<ApsClass>(pok) you are creating a new shared_ptr that doesn't know about all the other shared_ptr s pointing to the same object. 每次执行shared_ptr<ApsClass>(pok)您都在创建一个新的shared_ptr ,它不知道所有其他指向同一对象的shared_ptr So when this shared_ptr gets destroyed it will destroy the object. 因此,当此shared_ptr被销毁时,它将销毁该对象。

But because you do it several times (twice, in your case) the object gets destroyed more than once. 但是,由于您进行了多次(在您的情况下为两次),该对象被破坏的次数不止一次。

Only shared_ptr s created from normal pointers have this problem. 仅从普通指针创建的shared_ptr出现此问题。 Creating a shared_ptr from another shared_ptr is fine. 从另一个shared_ptr创建一个shared_ptr很好。

You should create a shared_ptr once - change this 您应该一次创建一个shared_ptr更改此设置

ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);

to this: 对此:

shared_ptr<ApsClass> aps(new DerivedClass(0.5));
shared_ptr<ApsClass> s = Foo.AddApsClass(aps);
Foo.DelApsClass(s);

and change ApsClass * to shared_ptr<ApsClass> everywhere else . 并改变ApsClass *shared_ptr<ApsClass> 其他地方

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM