代码之家  ›  专栏  ›  技术社区  ›  Bloops

C中向量元素的shared_ptr分割错误++

  •  4
  • Bloops  · 技术社区  · 7 年前

    我是C++新手,很难理解关系机制。我有PHP背景,有数据库和ORMs,我无法重现一个非常简单的案例。程序在“atomic.h”第49行出现分段错误时崩溃 { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } . 这个问题来自shared\u ptr,尽管我真的不知道如何使用智能指针(我已经阅读了数百篇文章和关于它们的问题,但仍然很神秘)。

    注意:我使用GCC6.3和C++17仅使用std编译,而不使用boost。

    class Car : public enable_shared_from_this<Car> {
        //...
    }
    
    template <class Type>
    class Repository<Type> {
        vector<Type> collection;
    public:
        shared_ptr<Type> getNew() {
           Type newType;
           collection.push_back(newType);
           return shared_ptr<Type>(&collection.back());
           // I also tried this but program fails at this line although it compiles fine.
           // return collection.back().shared_from_this();
        }
    }
    
    class MainApp {
        Repository<Cars> cars;
        shared_ptr<Car> myCar;
    
    public:
        MainApp() {
            myCar = cars.getNew();
        }
    }
    
    int main() {
        MainApp app; // OK - myCar points to the last car in cars repository
        return 0; // SIGEGV Segmentation fault
    }
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   luantkow    7 年前

    TLDN'R:您应该在存储库中使用std::shared\u ptr的向量,或者更改 getNewCar 返回引用。

    我对您的代码做了一些修改,使输出更加详细:

    #include <memory>
    #include <iostream>
    #include <vector>
    
    class Car
    {
    public:
        Car()
        {
            std::cout << "Car ctor @" << this << std::endl;
        }
    
        Car(const Car& car)
        {
            std::cout << "Car copy ctor @" << this << " from " << &car << std::endl;
        }
    
        Car& operator=(const Car& car)
        {
            std::cout << "Car assign operator @" << this << std::endl;
        }
    
        ~Car()
        {
            std::cout << "Car dtor @" << this << std::endl;
        }
    };
    
    class Repository
    {
        std::vector<Car> collection;
    public:
        std::shared_ptr<Car> getNewCar()
        {
            Car newType;
            collection.push_back(newType);
            return std::shared_ptr<Car>(&collection.back());
        }
    };
    
    int main()
    {
        Repository rep;
        std::shared_ptr<Car> myCar = rep.getNewCar();
        return 0;
    }
    

    代码结果为:

    Car ctor @0x7ffe35557217
    Car copy ctor @0x25b6030 from 0x7ffe35557217
    Car dtor @0x7ffe35557217
    Car dtor @0x25b6030
    Car dtor @0x25b6030
    

    这个 std::vector 您在存储库中使用的对象在被销毁时负责删除其所有对象。最后一个指向某个对象的“std::shared\u ptr”也负责这样做。

    直线:

    return shared_ptr<Type>(&collection.back());
    

    获取当前所属对象的地址 标准::矢量 并创建 std::shared_ptr 使用指针。这 std::shared\u ptr 认为它是第一个跟踪对象的智能指针。因此,当它被销毁时(或者如果您制作了一些,则为其最后一个副本),将调用该对象析构函数。

    因此,如果您认为汽车的寿命将比其来源的存储库长:

    class Repository
    {
        std::vector<std::shared_ptr<Car>> collection;
    public:
        std::shared_ptr<Car> getNewCar()
        {
            collection.push_back(std::shared_ptr<Car>(new Car()));
            return collection.back();
        }
    };
    

    class Repository
    {
        std::vector<Car> collection;
    public:
        Car& getNewCar()
        {
            Car newCar;
            collection.push_back(newCar);
            return collection.back();
        }
    };