我有两个指向相同shared_ptrint,即在它们上调用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才会增加一。
std::shared_ptruse_count是仅通过原始指针的第一个shared_ptr的构造(或如果默认构造的话,分配给原始指针)再通过其他shared_ptr的复制构造或任何先前的shared_ptr的分配来增加?还有其他所有递增方式(如果有)?

最佳答案

当您将指针提供给shared_ptr时,该共享指针将获得该指针的所有权。您不再被允许对其进行delete编码,将其传递给另一个shared_ptr或类似名称。没有用于新shared_ptr的全局查找表,可以检查是否存在已经拥有指针或其他类似内容的另一个shared_ptr

换句话说,当通过传递相同的指针而不是复制shared_ptr本身(这会增加使用计数)创建第二个shared_ptr时,就会发生双重释放错误。您直到以后才能观察到未定义行为的事实不会改变它实际发生的位置。

07-24 15:18