类析构函数SEGFAULT

时间:2012-10-02 12:24:54

标签: c++ segmentation-fault destructor delete-operator

在我的项目中,我有两个类,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;

};

Production类:

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_map,其关键元素是一个字符串,值为list来自{{1}的元素}。class。

代码正常运行,Productionunordered_map已填充,但在调用list的标准析构函数类时,我遇到了分段错误。

据我所知,EarleyParser的默认析构函数应该调用EarleyParser的默认析构函数,该析构函数应该调用unordered_map的一个,它应该调用每个元素的默认析构函数list类的内容,如下所示:

Production

使用Valgrind和GDB进行反向跟踪并没有给我如何解决分段错误的帮助,这完全在析构函数44行的Production::~Production() { if( this->productionContent != NULL ) delete this->productionContent; <- line 44 } 中给出。

我应该实现析构函数类,还是默认的析构函数可以正常? 关于什么可能导致分段错误的任何想法?

添加复制构造

EarleyParser.cpp

4 个答案:

答案 0 :(得分:4)

你的三条规则是不完整的。由于您有指针成员,因此您需要确保已实现复制构造函数复制赋值运算符析构函数

现在,因为你有一个指向vector成员的指针,我会告诉你,不应该有,而是只有一个std::vector<std::string>std::unique_ptr<std::vector<std::string> >

我不知道为什么你决定需要一个指向容器的指针,但这主要不是一个好理由,而且容易出错。

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

指针的问题在于它们太容易作为“解决方案”被抓取,但实际上非常容易出错且难以使用。如果你停止考虑指针并且不再倾向于在每个转弯处使用它们,那么你就会有更轻松的时间。

答案 1 :(得分:1)

有两种选择。

  1. 要么在Production中动态分配向量,在这种情况下,需要赋值运算符来执行向量指针的深层复制。您的复制构造函数应该这样做。在这种情况下,您应该关注rule of three

  2. 或者,您在Production构造函数中指向一个向量,并且不执行深层复制,在这种情况下Production不拥有该向量,不应删除它析构函数。

  3. 如果您有案例1,我建议删除指针并按值保持std::vector

答案 2 :(得分:1)

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

这意味着productionContent!= NULL将永远为真,因为它开始是非NULL的事实。

在所有构造函数中尝试这样的事情:

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

答案 3 :(得分:0)

对于指针有任何好或坏的理由,使用std :: shared_ptr(作为成员和构造函数参数),你做的越少,你就越多。 std :: shared_ptr会为你做出nullptr和删除!