Recursion 返回0后出现SEGFULT;

Recursion 返回0后出现SEGFULT;,recursion,segmentation-fault,Recursion,Segmentation Fault,我写了一个程序来测试我的二叉树,当我运行它时,程序似乎崩溃了(btree.exe已经停止工作,Windows正在检查解决方案…) 当我通过调试器运行它,并将断点放在我怀疑导致它的函数destroy_tree()上时,它似乎按预期运行并返回到主函数。Main依次从程序返回,但随后光标跳回到destroy_tree(),并在自身内循环 下面是最小的代码示例,因此可以立即运行。我的编译器是MinGW,调试器是gdb(我使用的是Code::Blocks) #包括 使用名称空间std; 结构节点 { in

我写了一个程序来测试我的二叉树,当我运行它时,程序似乎崩溃了(btree.exe已经停止工作,Windows正在检查解决方案…)

当我通过调试器运行它,并将断点放在我怀疑导致它的函数destroy_tree()上时,它似乎按预期运行并返回到主函数。Main依次从程序返回,但随后光标跳回到destroy_tree(),并在自身内循环

下面是最小的代码示例,因此可以立即运行。我的编译器是MinGW,调试器是gdb(我使用的是Code::Blocks)

#包括
使用名称空间std;
结构节点
{
int key_值;
节点*左;
节点*右;
};
B类树
{
公众:
b树();
~b树();
无效插入(int键);
void destroy_tree();
私人:
节点*根;
void destroy_树(节点*叶);
无效插入(int键,节点*叶);
};
Btree::Btree()
{
root=NULL;
}
Btree::~Btree()
{
摧毁_树();
}
void Btree::destroy_tree()
{
摧毁_树(根);
coutleft!=NULL)
插入(键,叶->左);
其他的
{
叶->左=新节点;
叶->左->键\值=键;
叶->左->左=空;
叶->左->右=空;
}
}
否则如果(键>=叶->键值)
{
如果(叶->右!=NULL)
插入(键,叶->右);
其他的
{
叶->右=新节点;
叶->右->键\值=键;
叶->右->左=空;
叶->右->右=空;
}
}
}
void Btree::insert(int键)
{
if(root!=NULL)
{
插入(键,根);
}
其他的
{
根=新节点;
根->键\值=键;
根->左=空;
root->right=NULL;
}
}
int main()
{
树木;
int i;
树。插入(1);
树。摧毁树();
返回0;
}
另外,我计划从Code::Blocks内置调试器切换到DDD来调试这些问题。我听说DDD可以直观地显示指向对象的指针,而不仅仅是显示指针的地址。您认为切换是否有助于解决这些类型的问题(数据结构和算法问题)?

您的destroy_tree()被调用两次,您调用一次,然后在执行离开析构函数的main()后被调用

你可能认为它无论如何都应该工作,因为你检查了leaf=NULL,但delete不会将指针设置为NULL。因此,当第二次调用destroy_tree()时,您的根不是空的,

与您的问题没有直接关系(或者可能是这样),但最好给结构一个构造函数。例如:

struct node
{
    int key_value;
    node *left;
    node *right;

    node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
如果这样做,代码会变得更简单,因为在创建节点时不需要担心指针的设置,而且不可能忘记初始化它们


关于DDD,它it’这是一个很好的调试器,但坦率地说,调试的秘诀是首先编写正确的代码,所以您不必这样做。C++在这个方向上提供了很多帮助(比如使用构造函数),但是你必须理解并使用它提供的设施。

bTrut::破坏树在成功地对树进行核对后,不将根设置为0。因此,析构函数类destroy_tree()再次出现,您试图销毁已经销毁的对象


那将是未定义的行为:)。

一旦您销毁根目录。
确保它为NULL,这样它就不会再次尝试执行(从析构函数)


谢谢,我忘了当主返回时调用本地析构函数。尽管我建议您将所有内容重置为NULL,但这是一个很好的编程实践。谢谢您的提示。关于struct构造函数,我正在尝试实现它,但遇到编译错误。我想我会调查一下。你的意思是在“删除叶”之前设置“叶=NULL”,对吗?否则,它将尝试将未定义的指针设置为null no。删除后。删除操作后,指针叶指向无效内存。因此,您需要将leaf设置为usfull。
struct node
{
    int key_value;
    node *left;
    node *right;

    node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
void Btree::destroy_tree(node *leaf)
{
  if(leaf!=NULL)
  {
    destroy_tree(leaf->left);
    destroy_tree(leaf->right);
    delete leaf;

    leaf = NULL; // add this line
  }
}