二进制搜索树析构函数:free()无效指针

时间:2015-11-24 19:25:48

标签: c++ c++11 binary-search-tree destructor

对于我当前的编程分配,我必须构造一个二叉搜索树,并使用它按字母顺序从文件中插入单词,以制作一致性列表。程序完整,输出正确;该程序的主要部分完美。但是当程序完成并且调用析构函数时,它会与error in ./concordancebst : free(): invalid pointer崩溃。我不知道问题是什么,我的析构函数看起来会起作用并在线查看代码似乎它应该也能正常工作。我可以通过使用std::unique_ptr来解决这个问题,但从程序的范围来看似乎有点矫枉过正(在某种意义上我们还没有涵盖智能指针,我们在涉及动态内存的类已通过手动分配/解除分配处理。

BST.h

#ifndef BST_H
#define BST_H
#include <string>

class BST {
public:
   BST() { root = nullptr; }
   ~BST();

   void insert(const std::string word);
   int getCount(const std::string word);
   int length();

   friend std::ostream& operator << (std::ostream &out_s, BST b);
private:
   struct Node {
      std::string word;
      int count;
      Node *left;
      Node *right;
      Node() { word = ""; count = 0; left = nullptr; right = nullptr;}
      ~Node();
   };
   Node *root;

   void RInsert(Node* &t, std::string word);
   int countNodes(Node *p);
   void print(Node *p, std::ostream &out_s);
};
#endif

BST.cpp

#include "BST.h"
#include <string>
#include <iostream>
#include <iomanip>

BST::Node::~Node() {
   delete left;
   delete right;
}

BST::~BST() {
   delete root; 
}

int BST::countNodes(Node *p) {
   if(p == nullptr)
      return 0;
   else
      return countNodes(p->left) + countNodes(p->right) + 1;
}

int BST::getCount(const std::string word) {
   Node *p = root;
   while(true) {
      if(p == nullptr)
         return 0;
      else if(word.compare(p->word) < 0)
         p = p->left;
      else if(word.compare(p->word) == 0)
         return p->count;
      else
         p = p->right;
   }
}

int BST::length() {
   return countNodes(root);
}

void BST::RInsert(Node* &t, std::string word) {
   if(t == nullptr) {
      t = new Node;
      t->word = word;
      t->left = nullptr;
      t->right = nullptr;
      t->count++;
   }
   else if(word.compare(t->word) == 0)
      t->count++;
   else if(word.compare(t->word) < 0)
      RInsert(t->left, word);
   else //word.compare(t->word > 0)
      RInsert(t->right, word);
}

void BST::insert(const std::string word) {
   RInsert(root, word);
}

void BST::print(Node *p, std::ostream &out_s) {
   if(p != nullptr) {
      print(p->left, out_s);
      out_s << std::setw(13) << p->word << std::setw(10) << p->count <<  std::endl;
      print(p->right, out_s);
   }
}

std::ostream &operator << (std::ostream &out_s, BST b) {
   out_s << std::setw(13) << "Word" << std::setw(10) << "Count" << std::endl;
   out_s << "---------------------------------------------" << std::endl;
   b.print(b.root, out_s);
   out_s << "---------------------------------------------" << std::endl;
   out_s << "The file contains " << b.length() << " distinct words." << std::endl;

   return out_s;
}

1 个答案:

答案 0 :(得分:2)

std::ostream &operator << (std::ostream &out_s, BST b)
                                       Pass by value^. b is copied.

由于BST没有复制构造函数,因此调用默认复制构造函数并且不执行深层复制。 b包含源BST指针的副本,当从函数返回时销毁b时,它会将所有源Node与它一起带到严重。

修复有两个方面:

最直接,通过引用传递。

std::ostream &operator << (std::ostream &out_s, BST & b)

此代码间接违反了Rule of ThreeBSTBST::Node需要安全使用复制构造函数和赋值运算符。

修改

最小的测试用例如下:

#include <iostream>
#include "BST.h"

int main()
{
    BST t;

    t.insert("A");

    std::cout << t << std::endl;
    return 0;
}