Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::shared\u ptr中的一个bug?_C++_C++11_Shared Ptr_Object Lifetime - Fatal编程技术网

C++ std::shared\u ptr中的一个bug?

C++ std::shared\u ptr中的一个bug?,c++,c++11,shared-ptr,object-lifetime,C++,C++11,Shared Ptr,Object Lifetime,执行以下程序时会发生什么情况 #include <iostream> #include <memory> class test; std::shared_ptr<test> a_test_object; struct test { ~test() { std::cout << "destroy test" << std::endl; auto ptr = a_test_object;

执行以下程序时会发生什么情况

#include <iostream>
#include <memory>

class test;
std::shared_ptr<test> a_test_object;
struct test
{
    ~test()
    {
        std::cout << "destroy test" << std::endl;
        auto ptr = a_test_object;
    }
};

int main()
{
    a_test_object = std::make_shared<test>();
    //a_test_object.reset();  // Uncomment this and it works fine.
}
我在GCC和VisualStudio2015上都测试了这一点,在这两种情况下,程序都崩溃了。发生的情况是共享指针在其析构函数中递减计数,然后执行~test,它复制共享指针,递增计数,然后递减计数,从而触发对~test调用的无限递归。奇怪的是,调用reset并没有引发问题


我今天遇到这个问题是因为一些使用C++11之前版本的shared_ptr的旧代码被更新为使用std::shared_ptr,它没有双重删除错误。令我惊讶的是,std::shared_ptr使程序崩溃。这真的是std::shared\u ptr的预期行为吗

>你违反了C++对象生存期的基本规则:在生命周期结束后,你不能访问一个对象。只有当所有共享的_ptr实例都已结束其生命周期时,才能删除测试。因此,它的析构函数及其调用的所有代码都无法访问任何引用自身的共享_ptr实例

否则将调用未定义的行为。这不是shared_ptr中的错误;这是代码中的一个bug。若测试是向量中的一个对象,并试图在析构函数中访问该向量实例,那个么它也同样重要

令人恼火的是,那些可以用来工作的东西并不是因为迂腐的原因

这不是一个迂腐的理由。这是不可能的。一个测试对象不再存在;这不是一个有效的对象

它不起作用的原因与返回对堆栈变量的引用不起作用的原因相同。物体在这一点上消失了;你不能再访问它了


因此,您需要重新构造代码来处理这一事实。

进入析构函数~test的唯一方法是,如果某个对象的生存期已结束,那么在该对象的生存期结束后访问该对象是UB。我没有看到交战角度。在这种情况下,您希望shared_ptr做什么?我看不出这是怎么回事。一旦进入析构函数,共享的ptr控制块上的ref计数为0。然后将其分配给本地ptr变量,该变量将ref计数再次增加到1。当它超出范围时,计数再次下降到0,您将获得第二次自由。shared_ptr没有办法知道你一直在搞恶作剧。@DavisKing std::shared_ptr可以处理指向其他事物的复杂模式的事物-当然不能,不是在一般情况下。它可以提供共享所有权,仅此而已。@DavisKing:我的意思是,我们告诉人们std::shared\u ptr可以处理指向其他事物的复杂模式。不,我们没有。复杂的指向模式通常会导致循环引用,而shared_ptr绝对无法处理循环引用。对象的生命周期结束后,您无法访问该对象。这是库规则还是核心语言规则?@curiousguy:由于共享的\u ptr的析构函数调用了\u test\u对象的析构函数,因此进一步使用该共享的\u ptr实例属于[class.cdtor]。语言规则最终归结为它取决于对象。由于标准没有定义当前正在销毁的库对象的状态,因此根据定义,它们的状态是未定义的。因此,访问它们会导致未定义的行为。您的评论比您的答案更准确。共享\u ptr的析构函数正在执行。其成员毫无疑问完好无损。它的储存绝对完好无损。声称它已经不存在并且它不是一个有效的对象似乎是不对的。对于您在评论中提到的在dtor执行过程中可以做的有限事情的观察更令人信服。考虑重写吗?