У меня два shared_ptr
указывает на то же 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.
То же самое происходит в этом варианте с явно объявленным необработанным указателем:
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.
Почему use_count()
вернуть 1
(но нет 2
) если оба shared_ptr
указывает на то же самое? Если use_count()
возвращенный 1
Тогда почему была попытка освободить int
дважды? Я думал, что shared_ptr
вырастет use_count
один, если и только если он указывает на тот же адрес, что и его братья shared_ptr
s.
Это std::shared_ptr
«s use_count
увеличивается только на первое shared_ptr
конструирование по необработанному указателю (или присвоение необработанному указателю, если построено по умолчанию), а затем по дополнительному shared_ptr
s ‘copy-construction или уступка любым из предыдущих shared_ptr
s? И каковы все другие способы приращения, если таковые имеются?
Когда вы даете указатель на shared_ptr
этот общий указатель становится владельцем этого указателя. Вам больше не разрешено delete
это, передать его другому shared_ptr
, или похожие. Там нет глобальной таблицы поиска для нового shared_ptr
проверить, чтобы найти, что уже есть другой shared_ptr
который уже имеет указатель или что-то в этом роде.
Иными словами, ошибка двойного освобождения произошла, когда второй shared_ptr
был создан путем передачи в тот же указатель, а не копирование shared_ptr
сам (который увеличивает счетчик использования). Тот факт, что вы не можете наблюдать неопределенное поведение до тех пор, пока позже не изменится, где это происходит на самом деле.
Вы должны использовать конструктор копирования shared_ptr для правильного построения второго общего указателя.