2014-11-05 64 views
2

我有兩個shared_ptr指向相同的int,即在他們呼叫get()返回相同的地址。但撥打use_count()返回1。當他們最後超出範圍,它會嘗試釋放已被另一種釋放的內存,導致雙自由運行時錯誤:std :: shared_ptr的use_count遞增的方式是什麼?

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

int main() { 
    shared_ptr<int> sp1(make_shared<int>(7)); 
    shared_ptr<int> sp2(&(*sp1)); 
    cout << sp1.use_count() << endl; // 1 
    cout << sp2.use_count() << endl; // 1 
    cout << sp1.get() << endl;  // same address 
    cout << sp2.get() << endl;  // same address 
} 
//^Double free runtime error at closing brace. 

同樣的事情發生在這個變體具有顯式聲明的原始指針:

int main() { 
    int *raw_ptr = new int(8); 
    shared_ptr<int> sp3(raw_ptr); 
    shared_ptr<int> sp4(raw_ptr); 
    cout << sp3.use_count() << endl; // 1 
    cout << sp4.use_count() << endl; // 1 
    cout << sp3.get() << endl;  // same address 
    cout << sp4.get() << endl;  // same address 
} 
//^Double free runtime error at closing brace. 

爲什麼如果兩個shared_ptr小號點use_count()回報1(但不2),以同樣的事情?如果use_count()返回1,那麼爲什麼有試圖釋放兩次int?我認爲shared_ptr會將use_count增加1,當且僅當它指向與其弟弟shared_ptr s相同的地址。

是S建設由原始指針「僅由第一shared_ptr遞增小號use_count‘一個std::shared_ptr(或分配到原始指針中,如果默認構造的),然後通過附加的shared_ptr s’的複製結構或分配由任何的之前shared_ptr s?如果有的話,還有什麼其他的增值方式?

+1

嘗試改爲'shared_ptr sp4 = sp3;'。您需要複製共享指針對象本身;用相同的原始指針創建一個新的共享指針只意味着你有兩個共享指針,每個指針都認爲它們擁有對象的獨佔所有權。如果你改用'shared_ptr sp3(new int(8));' - 不要讓程序中的原始指針可見,以免意外使用它,這會更容易。 – cdhowie 2014-11-05 22:10:06

+1

其實,更好的辦法是'auto sp3 = std :: make_shared (8);'因爲這允許C++實現在單個內存分配中爲'int'和'shared_ptr'控制塊分配空間。 (這個標準不需要這個優化,但是它確實允許,如果你使用'shared_ptr (new int(8))',那麼這個優化是不可能的。) – cdhowie 2014-11-05 22:17:41

+0

@cdhowie,好點。我的評論只是爲了讓別人更清楚,如果做'shared_ptr sp3(new int(8)); shared_ptr sp4(new int(8));''''sp3'和'sp4'指向具有相同值的不同'int'(在不同的地址)。 – CodeBricks 2014-11-05 22:22:00

回答

6

當您給shared_ptr指針時,該共享指針將獲得該指針的所有權。您不再被允許使用delete它,將它傳遞給另一個shared_ptr或類似的。新的shared_ptr沒有全局查找表來檢查是否已經有另一個shared_ptr,它已經擁有指針或類似的東西。

換言之,當第二個shared_ptr是通過傳遞相同的指針創建的,而不是複製shared_ptr本身(它增加了使用計數)時,發生了雙重空閒錯誤。事實上,你不能觀察到未定義的行爲,直到後來纔會改變它實際發生的地方。

+0

那麼其他的'shared_ptr's'拷貝構造和賦值只有*方法來增加'use_count'嗎? – CodeBricks 2014-11-05 22:11:45

+1

@CodeBricks是的。否則,必須有一些全局的原始指針表,這樣當你從一個原始指針構造一個全新的實例時,它可以查找引用計數對象,並且這將需要與多線程程序中的全局表同步。這將是一場噩夢。 – cdhowie 2014-11-05 22:12:57

+0

@codeBricks:唯一不會觸發未定義行爲的方式,是的。 (有一堆掛起'shared_ptr'的成員函數可能會改變這一點;我對所有內容都不是完全正面的;但是任何其他成員的行爲都像複製構建或複製分配一樣) – 2014-11-05 22:14:11

1

您應該使用shared_ptr的複製構造函數來正確構造第二個共享指針。

+0

現在,如果你也解釋了爲什麼,而不僅僅是告訴你該怎麼做...... – Deduplicator 2014-11-05 22:05:53

相關問題