2009-06-14 69 views
2

我写了一个程序来测试我的二叉树,当我运行它,程序似乎崩溃(btree.exe已停止工作,Windows正在检查解决方案...)。段落错误后返回0;

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

最小代码示例如下,因此它可以立即运行。我的编译器是MinGW,我的调试器是gdb(我使用的是Code :: Blocks)。另外,我计划从Code :: Blocks内置调试器切换到DDD以调试这些问题。我听说DDD可以直观地显示指向对象的指针,而不是显示指针的地址。你认为制作交换机将有助于解决这些类型的问题(数据结构和算法问题)吗?

回答

4

你的destroy_tree()被调用两次,你调用它一次,然后它在析构函数离开main()后被调用。

您可能认为它应该工作,因为您检查leaf!= NULL,但删除不会将指针设置为NULL。所以,你根本不为空时destroy_tree()被调用第二次,

+0

谢谢,我忘了当地的析构函数被调用时,主要的回报 – Steve 2009-06-14 19:53:26

+0

酷。尽管让我建议你将所有东西都重置为NULL,但这是一个很好的编程习惯。 – PaV 2009-06-14 19:56:25

0

没有直接关系(或者也许是)你的问题,但它是很好的做法,让结构构造。例如:

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

    node(int val) : key_val(val), left(NULL), right(NULL) {} 
}; 

如果你这样做,你的代码变得更简单,因为你并不需要,当你创建一个节点设置指针忧虑,这是不可能忘记初始化它们。

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

+0

感谢您的提示。关于结构构造,我想实现,但收到编译错误。我想我会研究它。 – Steve 2009-06-14 19:59:05

0

Btree :: destroy_tree在成功添加树之后未将“root”设置为0。其结果是,析构函数类destroy_tree()再次和你试图破坏已毁的对象。

这将是未定义的行为,然后:)。

0

一旦你摧毁了根。
确保它是空,因此它不会尝试做一遍(从析构函数)

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

    leaf = NULL; // add this line 
    } 
}