尝试在二进制树中赋值时出现分段错误
Getting Segmentation Fault when trying to assign value in Binary Tree
我正在为我的C++类做一个BinaryTree项目,但我一直遇到分段错误。在TreeNode类的setValue()函数中,它不断打断我试图将x赋值给值的地方。有人知道为什么会发生这种事吗?
这是我的树节点类:
#ifndef TREENODE_H
#define TREENODE_H
#include <iostream>
template<typename T>
class TreeNode{
private:
T value;
TreeNode* left;
TreeNode* right;
public:
TreeNode();
TreeNode(const T&);
~TreeNode();
T& getValue();
TreeNode* getLeft() const;
TreeNode* getRight() const;
void setValue(const T&);
void setLeft(TreeNode*);
void setRight(TreeNode*);
};
template<typename T>
TreeNode<T>::TreeNode()
{
value = 0;
left = NULL;
right = NULL;
}
template<typename T>
TreeNode<T>::TreeNode(const T& x)
{
value = x;
left = NULL;
right = NULL;
}
template<typename T>
TreeNode<T>::~TreeNode()
{
if(left!=NULL)
delete left;
if(right!=NULL)
delete right;
}
template<typename T>
void TreeNode<T>::setValue(const T& x)
{
value=x;
}
template<typename T>
T& TreeNode<T>::getValue()
{
return value;
}
template<typename T>
TreeNode<T>* TreeNode<T>::getLeft() const
{
return left;
}
template<typename T>
TreeNode<T>* TreeNode<T>::getRight() const
{
return right;
}
template<typename T>
void TreeNode<T>::setLeft(TreeNode* x)
{
if(left!=NULL)
delete left;
left=new TreeNode;
left=x;
}
template<typename T>
void TreeNode<T>::setRight(TreeNode* x)
{
if(right!=NULL)
delete right;
right=new TreeNode;
right=x;
}
#endif
这是我的BinaryTree类:
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include "TreeNode.h"
#include <iostream>
template<typename T>
class BinaryTree:public TreeNode<T>{
public:
BinaryTree();
BinaryTree(const T&);
~BinaryTree();
BinaryTree(const BinaryTree&);
void insert(const T&);
void inorder_traversal();
private:
TreeNode<T>* root;
TreeNode<T>* getRoot();
void setRoot(const T&);
void destroyTree(TreeNode<T>*);
};
template<typename T>
BinaryTree<T>::BinaryTree()
{
root = new TreeNode <T>;
root = NULL;
}
template<typename T>
BinaryTree<T>::BinaryTree(const T& x)
{
root = new TreeNode <T>(x);
}
template<typename T>
BinaryTree<T>::BinaryTree(const BinaryTree<T>& A)
{
root=A.getRoot();
}
template<typename T>
void BinaryTree<T>::destroyTree(TreeNode<T>* leaf)
{
if(leaf!=NULL)
{
destroyTree(leaf->getLeft());
destroyTree(leaf->getRight());
delete leaf;
}
}
template<typename T>
BinaryTree<T>::~BinaryTree()
{
if(root!=NULL)
destroyTree(root);
}
template<typename T>
TreeNode<T>* BinaryTree<T>::getRoot()
{
return root;
}
template<typename T>
void BinaryTree<T>::setRoot(const T& x)
{
if(root!=NULL)
{
delete root;
root=new TreeNode<T>;
}
root->setValue(x);
}
template<typename T>
void BinaryTree<T>::insert(const T& x)
{
if (root == NULL)
setRoot(x);
else
{
TreeNode<T>* rootTemp = new TreeNode < T > ;
rootTemp = root;
bool insertionComplete = false;
while (!insertionComplete)
{
if (x < rootTemp->getValue())
{
if ((rootTemp->getLeft()) == NULL)
{
(rootTemp->getLeft())->setValue(x);
insertionComplete = true;
}
else
rootTemp = rootTemp->getLeft();
}
else
{
if ((rootTemp->getRight()) == NULL)
{
(rootTemp->getRight())->setValue(x);
insertionComplete = true;
}
else
rootTemp = rootTemp->getRight();
}
}
root = rootTemp;
delete rootTemp;
}
}
#endif
这是我正在尝试运行的简单main.cpp:
#include "TreeNode.h"
#include "BinaryTree.h"
#include <iostream>
int main()
{
BinaryTree<int> x(2);
std::cout << "firstn";
x.insert(1);
std::cout<<"ENDn";
return 0;
}
在您的类中,您有以下代码
if (x < rootTemp->getValue())
{
if ((rootTemp->getLeft()) == NULL)
{
(rootTemp->getLeft())->setValue(x);
insertionComplete = true;
}
else
rootTemp = rootTemp->getLeft();
}
else
{
if ((rootTemp->getRight()) == NULL)
{
(rootTemp->getRight())->setValue(x);
insertionComplete = true;
}
else
rootTemp = rootTemp->getRight();
}
当对象是NULL
时,您基本上是在调用setValue()
。您必须从TreeNode
对象初始化left
和/或right
,然后才能使用它们
没有过多的调试(我把它作为家庭作业留给你),这段代码:
TreeNode<T>* rootTemp = new TreeNode < T > ;
rootTemp = root;
看起来像是创建了一个对象(rootTemp
),然后通过将其重新分配给root
对象立即将其丢弃。进一步研究此处实现的逻辑。
if((rootTemp->getLeft())==NULL){(rootTemp->getLeft())->setValue(x)
您正在检查getLeft是否为NULL,然后取消对它的引用。
您的void BinaryTree::insert(const T&x)有一些缺陷:
您创建了一个新的TreeNode对象,并立即覆盖指向它的指针。这个新对象现在丢失了。进入太空。只需放下第一行
TreeNode<T>* rootTemp = new TreeNode < T >;
rootTemp = root;
最后覆盖根节点,旧的根节点现在就会丢失。进入太空。然后删除新的根节点(rootTemp)。任何对根节点的下一次访问现在都将崩溃。把两行都放下。
root = rootTemp;
delete rootTemp;
当您发现一个指向节点的空指针(指针为NULL)时,您将调用该指针的setValue。NULL表示后面没有对象可以执行您的操作=>分段错误(只是说您访问了一个不存在的对象)
(rootTemp->getLeft())->setValue(x);
不过,TreeNode提供了适当的函数setLeft()。这里也是创建新树节点的理想场所:
rootTemp->setLeft(new TreeNode<T>(x));
由于构造函数重载,您甚至不需要调用集合值。
正如其他人所指出的,你还没有完全理解指针是如何工作的,以及新指针和删除指针的作用。
- new=>在内存中创建并调用构造函数成员函数,返回内存地址
- delete=>调用析构函数成员函数并删除内存(告诉内存管理,内存现在可以被其他人使用)
- pointer=>只是一个地址,告诉CPU在内存中查找对象的位置
这会让你结束。但是您的程序在那之后由于对同一内存的双重删除而崩溃。如果你正在运行linux,你可以使用gdb来调试你的程序。只要打电话给gdb/您的程序位于正确目录下的终端中。"start"将启动程序,"continue"将告诉程序在停止(称为断点)后继续运行,"backtrace"有助于显示程序停止时调用了哪个函数。大多数IDE都有一个到gdb的接口,或者包含自己的调试器。
更进一步,您还会有一些额外的内存泄漏(您创建的对象会丢失,而且永远不会删除)。你可以用valgrind来搜索它们——leak-check=full/您的程序
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?