簡體   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