c ++ shared_ptr继承内存问题"错误释放"

sis*_*hke 1 c++ inheritance memory-management shared-ptr virtual-destructor

我按照给定的指示尝试解决大学问题.代码编译但会产生关于内存的警告.以下是代码的关键:

#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;
}
Run Code Online (Sandbox Code Playgroud)

main()基本上是来自自动测试的代码,我应该修改程序的其余部分以使main()正常工作.
警告是在派生类*的析构函数定义中报告的,它只是在翻译成英语时说"Bad deallocation".我的问题是:代码中出现此问题的位置和原因是什么?

我删除的代码对内存分配没有影响(我希望),并通过autotesting进行测试,我没有太多访问权限.其中一项测试报告以下内容:

Invalid read of size 8 ...  
Address 0x51f0090 is 0 bytes inside a block of size 56 free'd 
Run Code Online (Sandbox Code Playgroud)

==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
Run Code Online (Sandbox Code Playgroud)

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

如果需要进一步的细节,我可以在这里放一些原始代码.

use*_*751 6

每次你shared_ptr<ApsClass>(pok)创建一个新的shared_ptr,不知道shared_ptr指向同一个对象的所有其他s.因此,当它shared_ptr被破坏时,它将破坏对象.

但是因为你做了好几次(在你的情况下是两次),对象会不止一次被破坏.

只有shared_ptr从普通指针创建的s才会出现此问题.shared_ptr从另一个创建一个shared_ptr很好.

你应该创建shared_ptr 一次 - 改变它

ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
Run Code Online (Sandbox Code Playgroud)

对此:

shared_ptr<ApsClass> aps(new DerivedClass(0.5));
shared_ptr<ApsClass> s = Foo.AddApsClass(aps);
Foo.DelApsClass(s);
Run Code Online (Sandbox Code Playgroud)

并改变ApsClass *shared_ptr<ApsClass> 其他地方.

  • 我同意那个.一旦原始指针由`shared_ptr`管理,就不再使用原始指针(除了与遗留代码接口,但在这种情况下你将使用`shared_ptr :: get()`).相反,只传递`shared_ptr`(或者在你需要阻止循环引用的情况下,一个`weak_ptr`),这将避免这样的问题. (3认同)