逻辑上的'双重释放或损坏(fasttop)'错误

问题描述 投票:0回答:2

我正在执行一些Binary Search Tree作业,并且出现了这个“双重释放或损坏(快速运行)”错误。

*** Error in `./bin/Main': double free or corruption (fasttop): 0x0000000000c25c20 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f9546af77e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f9546b0037a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f9546b0453c]
./bin/Main[0x400f21]
./bin/Main[0x400e1b]
./bin/Main[0x400d8c]
./bin/Main[0x400cc0]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f9546aa0830]
./bin/Main[0x400b69]
======= Memory map: ========
00400000-00402000 r-xp 00000000 00:00 6594                       /home/alu0101228587/c++_projects/bin/Main
00402000-00403000 r-xp 00002000 00:00 6594                       /home/alu0101228587/c++_projects/bin/Main
00602000-00603000 r--p 00002000 00:00 6594                       /home/alu0101228587/c++_projects/bin/Main
00603000-00604000 rw-p 00003000 00:00 6594                       /home/alu0101228587/c++_projects/bin/Main
00c14000-00c46000 rw-p 00000000 00:00 0                          [heap]
7f9540000000-7f9540021000 rw-p 00000000 00:00 0
7f9540021000-7f9544000000 ---p 00000000 00:00 0
7f9546770000-7f9546878000 r-xp 00000000 00:00 811272             /lib/x86_64-linux-gnu/libm-2.23.so
7f9546878000-7f954687a000 ---p 00108000 00:00 811272             /lib/x86_64-linux-gnu/libm-2.23.so
7f954687a000-7f9546a77000 ---p 0000010a 00:00 811272             /lib/x86_64-linux-gnu/libm-2.23.so
7f9546a77000-7f9546a78000 r--p 00107000 00:00 811272             /lib/x86_64-linux-gnu/libm-2.23.so
7f9546a78000-7f9546a79000 rw-p 00108000 00:00 811272             /lib/x86_64-linux-gnu/libm-2.23.so
7f9546a80000-7f9546c40000 r-xp 00000000 00:00 808634             /lib/x86_64-linux-gnu/libc-2.23.so
7f9546c40000-7f9546c49000 ---p 001c0000 00:00 808634             /lib/x86_64-linux-gnu/libc-2.23.so
7f9546c49000-7f9546e40000 ---p 000001c9 00:00 808634             /lib/x86_64-linux-gnu/libc-2.23.so
7f9546e40000-7f9546e44000 r--p 001c0000 00:00 808634             /lib/x86_64-linux-gnu/libc-2.23.so
7f9546e44000-7f9546e46000 rw-p 001c4000 00:00 808634             /lib/x86_64-linux-gnu/libc-2.23.so
7f9546e46000-7f9546e4a000 rw-p 00000000 00:00 0
7f9546e50000-7f9546e66000 r-xp 00000000 00:00 808707             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9546e66000-7f9547065000 ---p 00000016 00:00 808707             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9547065000-7f9547066000 rw-p 00015000 00:00 808707             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9547070000-7f95471e2000 r-xp 00000000 00:00 840863             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f95471e2000-7f95471ef000 ---p 00172000 00:00 840863             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f95471ef000-7f95473e2000 ---p 0000017f 00:00 840863             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f95473e2000-7f95473ec000 r--p 00172000 00:00 840863             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f95473ec000-7f95473ee000 rw-p 0017c000 00:00 840863             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f95473ee000-7f95473f2000 rw-p 00000000 00:00 0
7f9547400000-7f9547425000 r-xp 00000000 00:00 808510             /lib/x86_64-linux-gnu/ld-2.23.so
7f9547425000-7f9547426000 r-xp 00025000 00:00 808510             /lib/x86_64-linux-gnu/ld-2.23.so
7f9547625000-7f9547626000 r--p 00025000 00:00 808510             /lib/x86_64-linux-gnu/ld-2.23.so
7f9547626000-7f9547627000 rw-p 00026000 00:00 808510             /lib/x86_64-linux-gnu/ld-2.23.so
7f9547627000-7f9547628000 rw-p 00000000 00:00 0
7f9547750000-7f9547751000 rw-p 00000000 00:00 0
7f9547760000-7f9547761000 rw-p 00000000 00:00 0
7f9547770000-7f9547772000 rw-p 00000000 00:00 0
7f9547780000-7f9547781000 rw-p 00000000 00:00 0
7f9547790000-7f9547791000 rw-p 00000000 00:00 0
7f95477a0000-7f95477a1000 rw-p 00000000 00:00 0
7fffe8039000-7fffe8839000 rw-p 00000000 00:00 0                  [stack]
7fffe8f7c000-7fffe8f7d000 r-xp 00000000 00:00 0                  [vdso]

这是主程序:

#include "bsearch_tree_s.cpp"
#include "../include/dni.hpp"

int main(void)
{   
  bsearch_tree_s<int> tree;

  tree.insert(20);
  tree.insert(6);
  tree.insert(1);
  tree.insert(90);
  tree.insert(23);

  tree.write(cout);

  return 0;
}

非常简单,因为我只是想测试我的课程。

事实是,通过注释Main程序中的各行,我注意到创建错误的方法是btree_c :: insert(int)。

b_search_tree_c类(子)头文件:

#ifndef __BSEARCH_TREE_S__
#define __BSEARCH_TREE_S__

#include "../src/btree_c.cpp"

using namespace std;

template <typename Clave = int>
class bsearch_tree_s: public btree_c<Clave>
{   public:
        bsearch_tree_s(void);

        bsearch_tree_s(bnode_c<Clave>*);

        ~bsearch_tree_s(void);

        ostream& write(ostream&) const;
};

#endif

bsearch_tree_c类(子)cpp文件:

#include "../include/bsearch_tree_s.hpp"

template <typename Clave>
bsearch_tree_s<Clave>::bsearch_tree_s(void):
btree_c<Clave>::btree_c() {}

template <typename Clave>
bsearch_tree_s<Clave>::~bsearch_tree_s(void)
{ btree_c<Clave>::~btree_c(); }

template <typename Clave>
ostream& bsearch_tree_s<Clave>::write(ostream& os) const
{   
  unsigned int root_level = 0;

  return btree_c<Clave>::print(os, btree_c<Clave>::root_, root_level);
}

btree_c类(父)头文件:

#ifndef __BTREE_C__
#define __BTREE_C__

#include <iostream>
#include <cstdio>
#include <cassert>

#include "../src/bnode_c.cpp"

using namespace std;

template <typename Clave = int>
class btree_c
{   
    protected:
        int depth_;

        unsigned int size_;

        bnode_c<Clave>* root_;

    public:
        btree_c(void);

        btree_c(bnode_c<Clave>*);

        ~btree_c(void);

        void cut(bnode_c<Clave>*);

        bool is_empty(void) const;

        ostream& print(ostream&, bnode_c<Clave>*, unsigned int) const;

        void insert(const Clave);

        bnode_c<Clave>* get_root(void) const;

    private:
        void insert_branch(const Clave, bnode_c<Clave>*&);
};

#endif

btree_c类(父)cpp文件:

#include "../include/btree_c.hpp"

using namespace std;

template <typename Clave>
btree_c<Clave>::btree_c(void):
depth_(-1),
size_(0),
root_(NULL) {}


template <typename Clave>
btree_c<Clave>::btree_c(bnode_c<Clave>* root):
depth_(0),
size_(1),
root_(root) {}


template <typename Clave>
btree_c<Clave>::~btree_c(void) { cut(root_); }


template <typename Clave>
void btree_c<Clave>::cut(bnode_c<Clave>* node)
{   if (node == NULL) return;

    cut(node->left_);
    cut(node->right_);

    delete node;
    node = NULL;
}

template <typename Clave>
ostream& btree_c<Clave>::print(ostream& os, bnode_c<Clave>* node, unsigned int level) const
{   if (node == NULL) return os;

    else
    {   
        os << "Level " << level << ": [" << node->get_data() << "]  " << endl;

        level++;

        print(os, node->left_, level);
        print(os, node->right_, level);

        return os;
    }
}

template <typename Clave>
void btree_c<Clave>::insert(const Clave clave)
{   if (root_ == NULL)
      root_ = new bnode_c<Clave>(clave);
    else 
      insert_branch(clave, root_);

    size_++;
}

template <typename Clave>
void btree_c<Clave>::insert_branch(const Clave clave, bnode_c<Clave>*& node)
{   if (node == NULL)
        node = new bnode_c<Clave>(clave);

    else if (clave < node->get_data())
        insert_branch(clave, node->left_);

    else insert_branch(clave, node->right_);
}

bnode_c头文件:

#ifndef __BNODE_C__
#define __BNODE_C__

#include <iostream>
#include <cstdio>
#include <cassert>

using namespace std;

template <typename TDato = int>
class bnode_c
{   private:
        TDato data_;

    public:
        bnode_c<TDato>* left_;

        bnode_c<TDato>* right_;

        bnode_c(void);

        bnode_c(const TDato&);

        ~bnode_c(void);

        TDato& get_data(void);
};

#endif

bnode_c类cpp文件:

#include "../include/bnode_c.hpp"

using namespace std;

template <typename TDato>
bnode_c<TDato>::bnode_c(void):
    left_(NULL),
    right_(NULL),
    data_(NULL) {}

template <typename TDato>
bnode_c<TDato>::bnode_c(const TDato& dat):
    left_(NULL),
    right_(NULL),
    data_(dat) {}


template <typename TDato>
bnode_c<TDato>::~bnode_c(void)
{   left_ = NULL;

    right_ = NULL;
}

template <typename TDato>
TDato& bnode_c<TDato>::get_data(void) { return data_;}

我不知道如何解决此问题,因为我的代码中从未出现此错误,因此需要您的帮助。

提前感谢。

c++ binary-tree binary-search-tree
2个回答
1
投票

您的bsearch_tree_s析构函数正在显式调用其超类析构函数:

template <typename Clave>
bsearch_tree_s<Clave>::~bsearch_tree_s(void)
{ btree_c<Clave>::~btree_c(); }

这是错误的:不需要这样做,无论如何它都会被自动调用,其结果是〜btree_c()将尝试删除其root_节点两次,因此产生了错误。暂时将跟踪输出添加到〜bsearch_tree_s和〜btree_c可能会值得一看。

在删除node后,您确实要清除cut指针,但是由于该值是通过不引用传递的,因此不会更改root_成员。另一种解决方法是在拥有root_ = NULL;后在〜btree_c()中设置cut


1
投票
template <typename Clave>
void btree_c<Clave>::cut(bnode_c<Clave>* node)
{   if (node == NULL) return;

    cut(node->left_);
    cut(node->right_);

    delete node;
    node = NULL; <---- this doesn't do anything
}

它需要添加&来做某事。

void btree_c<Clave>::cut(bnode_c<Clave>*& node)
© www.soinside.com 2019 - 2024. All rights reserved.