逻辑'double free or corruption (fasttop)'错误

Ilogical 'double free or corruption (fasttop)' error

本文关键字:fasttop 错误 free double 逻辑 or corruption      更新时间:2023-10-16

我正在做一些二叉搜索树作业,出现了这个"双重释放或损坏(快速顶部("错误。

*** 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;
}

这很简单,因为我只是想测试我的班级。

问题是,通过在主程序中注释行,我注意到创建错误的方法是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_;}

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

提前谢谢。

您的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_成员。另一种解决方法是在cut后在 ~btree_c(( 中设置root_ = NULL;

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)