【问题标题】:Class Destructor SEGFAULT类析构函数 SEGFAULT
【发布时间】:2012-09-23 07:13:07
【问题描述】:

在我的项目中,我有两个类,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 元素的 list 来自 Production 类。

代码工作正常,unordered_maplist 被填充,但是在调用 EarleyParser 的标准析构函数类时,我遇到了分段错误。

据我了解,EarleyParser 的默认析构函数应该调用unordered_map 的默认析构函数,它应该调用list 之一,它应该为它的每个元素调用Production 类的默认析构函数, 如下:

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

使用 Valgrind 和 GDB 进行回溯并没有给我太多帮助来解决分段错误,这在析构函数第 44 行的EarleyParser.cpp 中给出。

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

添加的副本构造函数

Production::Production( const Production& copy_me )
{
    if( this->productionContent != NULL )
        this->productionContent = NULL;

    this->setProductionProbability( copy_me.productionProbability );
    this->setProductionLength( copy_me.productionLength );

    this->setProductionContent( copy_me.productionContent );

}

【问题讨论】:

  • 在您的复制构造函数中,您是只复制指针还是进行“深度”复制? 为什么你有一个指向容器的指针?为什么不用参考?
  • Production 的复制 ctor 是什么样的,为什么你的析构函数是虚拟的?另外,Production 是否也拥有 vector?如果是,为什么是指针,如果不是,为什么要删除它?
  • vector&lt; string &gt;* getProductionContent(); 这让我恶心。 Urgh 指向容器的指针。
  • @Xeo - 我添加了复制构造函数
  • @TonyTheLion - 我用这个选项编译std=c++0x,所以我相信是的......

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


【解决方案1】:

有两种选择。

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

  2. 1234563 /p>

如果您有第 1 种情况,我建议您删除指针并按值持有 std::vector

【讨论】:

    【解决方案2】:

    你的三法则不完整。因为你有一个指针成员,你要确保已经实现了复制构造函数复制赋值操作符析构函数

    现在,因为你有一个指向 vector 成员的指针,我要告诉你,你不应该有那个,而是只有一个 std::vector&lt;std::string&gt; 或 @987654323 @。

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

    你可以持有一个容器的reference,但你需要确保它在ctor中被初始化。

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2017-03-21
          • 2020-02-29
          • 2016-10-12
          • 1970-01-01
          • 2014-05-27
          • 2011-09-01
          • 2018-11-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多