C++ 类析构函数SEGFAULT

C++ 类析构函数SEGFAULT,c++,segmentation-fault,destructor,delete-operator,C++,Segmentation Fault,Destructor,Delete Operator,在我的项目中,我有两个类,EarleyParser类: class EarleyParser { public: EarleyParser(); virtual ~EarleyParser(); void initialize( string filePath, bool probabilityParse ); private: bool probabilityParser; typede

在我的项目中,我有两个类,
EarleyParser
类:

class EarleyParser
{

    public:

        EarleyParser();
        virtual ~EarleyParser();

        void initialize( string filePath, bool probabilityParse );

    private:

        bool probabilityParser;

        typedef unordered_map< string, list<Production> > productionHashTable;
        productionHashTable earlyHashTable;

};
class Production
{
    public:

        Production();

        Production( float productionProbability, int productionLength, vector< string >* productionContent );

        Production( const Production& copy_me );

        virtual ~Production();

        float getProductionProbability();
        int getProductionLength();
        vector< string >* getProductionContent();

    private:

        float productionProbability;
        int productionLength;
        vector< string >* productionContent;

        void setProductionProbability( float productionProbability );
        void setProductionLength( int productionLength );
        void setProductionContent( vector< string >* productionContent );

};
正如您在上面所看到的,
EarlyParser
类有一个成员元素,它是一个,其关键元素是一个字符串,而值是来自
生产类的一组元素

代码工作正常,
unordered_映射
列表
会被填充,但是调用
EarleyParser的标准析构函数类
时会出现分段错误

据我所知,
EarleyParser
的默认析构函数应该调用
unordered_map
的默认析构函数,该析构函数应该调用
列表中的一个
,该列表应该为其每个元素调用
Production
类的默认析构函数,如下所示:

Production::~Production()
{
    if( this->productionContent != NULL )
        delete this->productionContent; <- line 44
}

有两种选择

  • 您可以在
    生产中动态分配向量,在这种情况下,您需要一个赋值运算符来执行向量指针的深度复制。复制构造函数也应该这样做。在这种情况下,您应该遵循以下步骤

  • 或者,您在
    Production
    构造函数中获取指向向量的指针,并且不执行深度复制,在这种情况下
    Production
    不拥有向量,不应在析构函数中删除它


  • 如果您有案例1,我建议您放下指针并按值按住
    std::vector

    您的三个规则不完整。因为您有一个指针成员,所以需要确保已经实现了复制构造函数、复制赋值运算符和析构函数

    现在,因为您有一个指向
    vector
    成员的指针,我要告诉您不应该有这个,而应该有一个
    std::vector
    或一个
    std::unique\u ptr

    我不知道为什么您决定需要保存指向容器的指针,但这绝不是一个好理由,而且很容易出错

    您可以保存对容器的引用,但需要确保它已在ctor中初始化


    指针的问题在于,它们太容易被当作“解决方案”,但实际上极易出错,很难使用。如果您不再考虑指针,也不再倾向于在每一个转折点都使用它们,那么您的工作就会轻松得多。

    我没有看到productionContent变量的任何初始化。尝试使用初始值设定项将其初始化为NULL。未初始化成员变量的默认值不为null

    这意味着productionContent!=NULL将始终为true,因为它开始时不是NULL

    在所有构造函数中尝试以下操作:

    Production::Production( const Production& copy_me ) : productionContent(NULL)
    {
    ...
    

    对于指针的任何好的或坏的理由,请使用std::shared_ptr(作为成员和构造函数参数),做得越少,做得越多。std::shared_ptr将为您创建空ptr和删除

    在复制构造函数中,是复制指针还是进行“深度”复制?为什么有一个指向容器的指针?为什么不改为引用呢?
    Production
    的复制构造函数是什么样子的,为什么析构函数是虚拟的?另外,
    Production
    是否拥有
    vector
    ?如果是,为什么它是指针;如果不是,为什么要删除它?
    vector*getProductionContent()Production::Production( const Production& copy_me ) : productionContent(NULL)
    {
    ...