3

shared_ptr同じ を指す2 つの があります。intつまり、それらを呼び出すget()と同じアドレスが返されます。しかし、それらを呼び出すuse_count()と が返されます1。それらの最後のものが範囲外になると、もう一方によってすでに解放されているメモリを解放しようとするため、二重解放の実行時エラーが発生します。

#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.

このバリアントでも、明示的に宣言された raw ポインターを使用して同じことが起こります。

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.

両方の s が同じものを指している場合、 がuse_count()返される1(返されない) のはなぜですか? が返された場合、 2 回解放しようとしたのはなぜですか? a は、その兄弟の s と同じアドレスを指している場合にのみ、1増加すると考えました。2shared_ptruse_count()1intshared_ptruse_countshared_ptr

のは、生std::shared_ptrのポインタ (またはデフォルトで構築されている場合は生のポインタへの代入) によるuse_count最初の の構築によってのみインクリメントされ、その後、追加の のコピー構築または前の のいずれかによる代入によってインクリメントされますか? また、インクリメントする他のすべての方法は何ですか?shared_ptrshared_ptrshared_ptr

4

2 に答える 2

6

へのポインターを渡すとshared_ptr、その共有ポインターがそのポインターの所有権を取得します。もう許可されていないか、別の、または同様deleteのものに渡します。既にポインターを所有している別のテーブルが既に存在するかどうかを確認するshared_ptrために、新規作成者がチェックするグローバル ルックアップ テーブルはありません。shared_ptrshared_ptr

別の言い方をすれば、それ自体をshared_ptrコピーするのではなく、同じポインターを渡すことによって秒が作成されたときに、二重解放エラーが発生しましたshared_ptr(使用カウントが増加します)。後になるまで未定義の動作を観察できないという事実は、それが実際に発生する場所を変更しません。

于 2014-11-05T22:02:55.893 に答える
1

2 番目の共有ポインターを適切に構築するには、shared_ptr のコピー コンストラクターを使用する必要があります。

于 2014-11-05T22:02:52.040 に答える