【问题标题】:Destructor for BSTBST 的析构函数
【发布时间】:2013-04-13 08:49:00
【问题描述】:

我必须实现自己的二叉搜索树。据我所知,除析构函数外,一切正常。 这是一些代码(所有析构函数和构造函数)

Node(){
        val = T();
        parent=nullptr;
        lChild = nullptr;
        rChild = nullptr;
    }
    Node(T &valx){
        val=valx;
        parent=nullptr;
        lChild = nullptr;
        rChild = nullptr;
    }
    Node(const Node &other){
        val = other.val;
        if(other.lChild!=nullptr){
            lChild = new Node(*other.lChild);
            lChild->parent=this;
        }
        else
            lChild=nullptr;
        if(other.rChild!=nullptr){
            rChild= new Node(*other.rChild);
            rChild->parent=this;
        }
        else
            rChild=nullptr;
    }
    ~Node(){
        if(lChild!=nullptr){
            delete lChild; 
            lChild=nullptr; 
        }
        if(rChild!=nullptr){
            delete rChild; 
            rChild=nullptr; 
        }
    }

Set(){
    root = nullptr;
    sizeOfTree=0;
}
Set(const Set &other){
    if(other.root!=nullptr){
        root = new Node(*other.root);
        root->parent=nullptr;
    }
    else
        root=nullptr;
    sizeOfTree=other.sizeOfTree;
}
~Set()
{
    if(root!=nullptr){
        delete root;
        //root->~Node();
        root=nullptr;
    }
}

通过最简单的测试,valgrind 显示 272 个错误。感谢您的帮助

@edit:valgrind 输出的一部分:

==6981== Invalid read of size 8
==6981==    at 0x405C29: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:53)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x404790: Plansza::~Plansza() (in /media/Dokumenty/Workspace/JakbyGomoku4/Debug/JakbyGomoku4)
==6981==    by 0x4015F0: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c34468 is 24 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401E27: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:315)
==6981==    by 0x4015A6: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid read of size 8
==6981==    at 0x405C5F: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:57)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x404790: Plansza::~Plansza() (in /media/Dokumenty/Workspace/JakbyGomoku4/Debug/JakbyGomoku4)
==6981==    by 0x4015F0: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c34470 is 32 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401E27: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:315)
==6981==    by 0x4015A6: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid free() / delete / delete[] / realloc()
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x404790: Plansza::~Plansza() (in /media/Dokumenty/Workspace/JakbyGomoku4/Debug/JakbyGomoku4)
==6981==    by 0x4015F0: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c34450 is 0 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401E27: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:315)
==6981==    by 0x4015A6: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:718)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid read of size 8
==6981==    at 0x405C6C: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:58)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x4057AF: Set<Pionek>::clear() (JakbyGomoku4.cpp:222)
==6981==    by 0x40160B: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:731)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c334c0 is 32 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401E27: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:315)
==6981==    by 0x4016DE: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:742)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid write of size 8
==6981==    at 0x405C89: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:59)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x4057AF: Set<Pionek>::clear() (JakbyGomoku4.cpp:222)
==6981==    by 0x40160B: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:731)
==6981==    by 0x401746: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:745)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c334c0 is 32 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401E27: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:315)
==6981==    by 0x4016DE: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:742)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid read of size 8
==6981==    at 0x405C36: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:54)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x40479C: Plansza::~Plansza() (in /media/Dokumenty/Workspace/JakbyGomoku4/Debug/JakbyGomoku4)
==6981==    by 0x401755: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:748)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c33448 is 24 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401DF0: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:314)
==6981==    by 0x4016DE: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:742)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981== 
==6981== Invalid write of size 8
==6981==    at 0x405C53: Set<Pionek>::Node::~Node() (JakbyGomoku4.cpp:55)
==6981==    by 0x4049EA: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x40479C: Plansza::~Plansza() (in /media/Dokumenty/Workspace/JakbyGomoku4/Debug/JakbyGomoku4)
==6981==    by 0x401755: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:748)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)
==6981==  Address 0x4c33448 is 24 bytes inside a block of size 40 free'd
==6981==    at 0x4A073CC: operator delete(void*) (vg_replace_malloc.c:480)
==6981==    by 0x4049F2: Set<Pionek>::~Set() (JakbyGomoku4.cpp:152)
==6981==    by 0x401DF0: Plansza::Plansza(Plansza const&) (JakbyGomoku4.cpp:314)
==6981==    by 0x4016DE: generujPlansze(Plansza&, int, bool, Set<Plansza>&) (JakbyGomoku4.cpp:742)
==6981==    by 0x4019D5: main (JakbyGomoku4.cpp:792)

【问题讨论】:

  • 请分享 valgrind 输出
  • 三法则……三法则……三法则……

标签: c++ memory destructor


【解决方案1】:

除了复制 ctor 和析构函数检查 here
之外,您还缺少 operator= 也无需检查析构函数中的 nullptr,it is ok to delelete nullptr
考虑类似

Node n1;
//set children for n1
{
Node n2;
//set children for n2
n1 = n2;//Now both n1 and n2 points same children, and initial children of n1 becomes mem leak
}//n2 destructor deletes its children leaving n1 pointing to the same already freed memory location

【讨论】:

  • 对于节点、集合还是两者?任何提示它应该是什么样子?
  • 两者都有析构函数和复制ctor。检查我发布的第一个链接,它已经包含详细的解释和示例。
  • 根据您发布的报告,这是问题所在。您创建节点,将一个节点分配给另一个节点,结果有 2 个节点指向相同的内存位置,一旦其中一个被删除,剩下的一个将保存指向已释放内存的指针。
  • 我已经研究了这个主题,如果我理解正确,我的 operator= 应该在 this!=that 的情况下执行析构函数,然后执行复制构造函数。我说的对吗?
  • 对,因为您要分配的对象需要从其他对象中提取数据。因此删除旧数据并将其替换为您将获得的任何数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 2018-08-29
  • 2014-05-27
  • 2011-04-16
  • 2011-04-03
相关资源
最近更新 更多