shared ptr出問題的幾種情況

2021-06-02 10:20:57 字數 3366 閱讀 2544

雖然boost.shared_ptr是個非常好的東西,使用它可以使得c++程式不需要考慮記憶體釋放的問題,但是還是有很多必須注意的地方。下面羅列了一些本人在實際工作中經常碰到的使用shared_ptr出問題的幾種情況。 

1.shared_ptr多次引用同一資料,如下:

int* pint = new int[100];

boost::shared_ptrsp1(pint);

// 一些其它**之後…

boost::shared_ptrsp2(pint);

這種情況在實際中是很容易發生的,結果也是非常致命的,它會導致兩次釋放同一塊記憶體,而破壞堆。 

2.使用shared_ptr包裝this指標帶來的問題,如下:

class tester

public:

tester()

~tester()

std::cout << "析構函式被呼叫!\n";

public:

boost::shared_ptrsget()

return boost::shared_ptr(this);

int main()

tester t;

boost::shared_ptrsp =  t.sget(); // …

return 0;

也將導致兩次釋放t物件破壞堆疊,一次是出棧時析構,一次就是shared_ptr析構。若有這種需要,可以使用下面**。

class tester : public boost::enable_shared_from_this

public:

tester()

~tester()

std::cout << "析構函式被呼叫!\n";

public:

boost::shared_ptrsget()

return shared_from_this();

int main()

boost::shared_ptrsp(new tester);

// 正確使用sp 指標。

sp->sget();

return 0;

3.shared_ptr迴圈引用導致記憶體洩露,**如下:

class parent;

class child; 

typedef boost::shared_ptrparent_ptr;

typedef boost::shared_ptrchild_ptr; 

class parent

public:

~parent()

~tester() {}

// 更多的函式定義…

void fun(boost::shared_ptrsp)

// !!!在這大量使用sp指標.

boost::shared_ptrtmp = sp;

int main()

boost::shared_ptrsp1(new tester);

// 開啟兩個執行緒,並將智慧型指標傳入使用。

boost::thread t1(boost::bind(&fun, sp1));

boost::thread t2(boost::bind(&fun, sp1));

t1.join();

t2.join();

return 0;

這個**帶來的問題很顯然,由於多執行緒同是訪問智慧型指標,並將其賦值到其它同類智慧型指標時,很可能發生兩個執行緒同時在操作引用計數(但並不一定絕對發生),而導致計數失敗或無效等情況,從而導致程式崩潰,如若不知根源,就無法查詢這個bug,那就只能向上帝祈禱程式能正常執行。

可能一般情況下並不會寫出上面這樣的**,但是下面這種**與上面的**同樣,如下:

class tester

public:

tester() {}

~tester() {}

public:

boost::shared_ptrm_spdata; // 可能其它型別。

tester gobject;

void fun(void)

// !!!在這大量使用sp指標.

boost::shared_ptrtmp = gobject.m_spdata;

int main()

// 多執行緒。

boost::thread t1(&fun);

boost::thread t2(&fun);

t1.join();

t2.join();

return 0;

情況是一樣的。要解決這類問題的辦法也很簡單,使用boost.weak_ptr就可以很方便解決這個問題。第一種情況修改**如下:

class tester

public:

tester() {}

~tester() {}

// 更多的函式定義…

void fun(boost::weak_ptrwp)

boost::shared_ptrsp = wp.lock;

if (sp)

// 在這裡可以安全的使用sp指標.

else

std::cout << 「指標已被釋放!」 << std::endl;

int main()

boost::shared_ptrsp1(new tester);

boost.weak_ptrwp(sp1);

// 開啟兩個執行緒,並將智慧型指標傳入使用。

boost::thread t1(boost::bind(&fun, wp));

boost::thread t2(boost::bind(&fun, wp));

t1.join();

t2.join();

return 0;

boost.weak_ptr指標功能一點都不weak,weak_ptr是一種可構造、可賦值以不增加引用計數來管理shared_ptr的指標,它可以方便的轉回到shared_ptr指標,使用weak_ptr.lock函式就可以得到乙個shared_ptr的指標,如果該指標已經被其它地方釋放,它則返回乙個空的shared_ptr,也可以使用weak_ptr.expired()來判斷乙個指標是否被釋放。

boost.weak_ptr不僅可以解決多執行緒訪問帶來的安全問題,而且還可以解決上面第三個問題迴圈引用。children類**修改如下,即可打破迴圈引用:

class child

public:

~child() {

std::cout <<"子類析構函式被呼叫.\n";

public:

boost::weak_ptrparent;

因為boost::weak_ptr不增加引用計數,所以可以在退出函式域時,正確的析構。

公募基金可能出問題的幾種情形

今年以來 在新一輪牛市中取得了優異的投資業績,高業績背後是 投資過程中頻頻涉足高風險地帶。5月下旬再融資重起之後,公司已經投資70多億參與上市公司定向增發,定向增發鎖定期帶來的流動性風險正在考驗 公司風險控制能力。在牛市環境中 高度集中持股現象有蔓延之勢,其中,多家 公司聯合高比例重倉持有同一 的投...

shared ptr跨模組邊界的問題

如果shared ptr預設是用delete來釋放物件的,而delete動作產生的是本模組的 這在windows平台的dll中遇到了問題 可執行程式和dll分屬不同模組,分別使用各自的記憶體管理元件。直接delete,無異於把a堆管理器分配的指標讓b堆管理其去釋放,崩潰還算好的,悄悄的出錯,死都不知...

Qstring的輸出問題

有時候想在控制台輸出我們想要的qstring變數。1 qdebug可以實現在控制台終端列印,但我們還是想使用c 中的std cout this function does nothing if qt no debug output was defined during compilation.2 網...