繁体   English   中英

了解智能指针但出错:未分配正在释放的指针

[英]Understanding smart pointers but error: pointer being freed was not allocated

我正在尝试了解智能指针,并具有以下代码:

 #include <iostream>
 #include <string>
 #include <memory>
 using namespace std;

 struct B 
 {
     string hello() { return "hello world"; }
 };

 class A
 {
 private:
     B* a;
 public:
     A() { a = new B; }
     ~A() { delete a; a = nullptr; }
     B* get() { return a; }
 };

 int main(int argc, const char * argv[]) {
     A a;
     shared_ptr<B> p(a.get());
     cout << p->hello() << endl;
     p.reset();
     return 0;
 }

我在这里想要做的是通过智能指针访问原始指针。 它可以很好地打印“ hello world”,并且在注释掉A的析构函数时没有错误。但是,当我取消注释时,出现以下错误:

 test(9758,0x7fff738d9300) malloc: *** error for object 0x1001053a0: pointer 
 being freed was not allocated
 *** set a breakpoint in malloc_error_break to debug

这里发生了什么? 当shared_ptr p超出范围或重置(重置为nullptr)时,它正在调用析构函数吗? p如何处理不删除A :: a引起的内存泄漏?

我了解智能指针通常会处理新对象,并且这种情况可能不经常使用,但是我想尝试学习这一点。

当shared_ptr p超出范围或重置(重置为nullptr)时,它正在调用析构函数吗?

对,就是这样。

p如何处理不删除A :: a引起的内存泄漏?

p认为它拥有对象,因此将其删除。 没有泄漏。 但是a也认为它也拥有该对象,因此它尝试第二次删除它并崩溃。

我了解智能指针通常会处理新对象,并且这种情况可能不经常使用,但是我想尝试学习这一点。

完全没有使用这种情况,因为正是由于这个原因,您不能让多个对象同时拥有相同的内存。

正确的解决方案是使class A内部使用shared_ptr

class A {
    private:
        shared_ptr<B> b;
    public:
        A() { b.reset(new B); }
        shared_ptr<B> get() { return b; }
};

int main(int argc, const char * argv[]) {
    A a;
    shared_ptr<B> p = a.get();
    cout << p->hello() << endl;
    p.reset();
    return 0;
}

或者干脆不拥有未直接分配给您的原始指针的所有权:

int main(int argc, const char * argv[]) {
    A a;
    B *p = a.get();
    cout << p->hello() << endl;
    return 0;
}

使用智能指针的全部要点是明确谁拥有什么以及如何转移所有权。 您的例子违反了这一点。

A a; shared_ptr<B> p(a.get()); 指向内存中相同的已分配B对象。 p.reset()破坏该B对象,然后将~A()的析构函数尝试再次释放它。

shared_ptr::reset()

如果*this已经拥有一个对象,并且它是拥有它的最后一个shared_ptr ,则该对象将通过拥有的deleter 销毁

您的p.reset()删除了B对象,因为它对拥有它的变量一无所知,并且您没有手动增加p的引用计数(对于shared_ptr来说这是不可能的,因为它被设计为仅通过复制共享一个指针) shared_ptr对象)。

您在此处尝试使用reset(ptr)进行的操作是未定义的行为:

如果ptr指向的对象已经拥有,则该函数将导致未定义的行为。

https://zh.cppreference.com/w/cpp/memory/shared_ptr/reset

暂无
暂无

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

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