【发布时间】:2021-08-10 20:03:42
【问题描述】:
所以我是一名 Python 程序员,我正在尝试自学 C。就像练习一样,我一直在尝试用 C 实现一个简单的二叉搜索树。我从来不需要处理内存分配或之前的指针,它导致了很多错误。
我的程序一直给我退出代码 -1073740940 (0xC0000374),我理解这意味着堆已损坏。这是一个有点长的程序,所以我只包含了有问题的函数。
使用 for 循环重复调用此插入函数,以将数组的内容插入二叉搜索树。数组的内容是5、4、6、3、7、2、8、1、9、0(目的是让树平衡)。
所以函数首先有 5 个传递给它。 pBST->listRoot 调用的指针为NULL(pBST 是一个指向列表结构的指针),所以插入5 作为根节点。这工作正常。然后将 4 传递给函数。由于已经有一个根,它会检查该根的子节点。 4 小于 5,所以检查 5 的左孩子。 5 的左子节点的指针为空,因此它尝试将 4 作为新节点插入。这是导致程序崩溃的那一行:
struct Node* pTemp = calloc(1, sizeof(struct Node));
我尝试了这行的几个变体。这是踢球者:cLion 的调试器无法重现这一点。当我通过调试器运行它时,它工作得很好。我认为这与调试器每次使用相同的内存地址以实现可重复性这一事实有关。我留下了调试 printf 语句并添加了 Node 和 binarySearchTree 结构的代码。
typedef struct Node BSTNode;
struct Node {
BSTNode* parent;
BSTNode* left;
BSTNode* right;
int* data;
};
typedef struct {
BSTNode* listRoot;
int nodeCount;
} binarySearchTree;
void insert(int Value, binarySearchTree* pBST) {
/*
* This function
*/
//====DEBUG CODE============
int debugIterations = 0;
printf("Now inserting %d \n", Value);
//=====END DEBUG CODE=======
//if no root, make it the root
if (pBST->listRoot == NULL) {
struct Node* newNode = calloc(1, sizeof(binarySearchTree));
(*pBST).listRoot = newNode;
(*pBST).listRoot->data;
(*pBST).listRoot->data = Value;
//pBST->listRoot->data = Value;
pBST->listRoot->parent = NULL;
pBST->listRoot->right = NULL;
pBST->listRoot->left = NULL;
return;
} else {
struct Node* pCursor = pBST->listRoot;
while (1){
printf("Iterations: %d \n", debugIterations);
debugIterations++;
//Check if the number is the same
if (pCursor->data == Value){
printf("ERROR: Tried to insert duplicate value into tree");
return;
}
//Is the value > the node?
else if (pCursor->data < Value) {
//DEBUG
printf("== check succeeded, now value > data\n");
// Is the value a Null?
if (pCursor->right == NULL) {
//DEBUG
printf("Running function to insert %d as a new node to the right\n", Value);
//If yes, then insert the value as a nul
//Create Node
struct Node* pTemp = calloc(1, sizeof(binarySearchTree));
pTemp->data = Value;
pTemp->parent = pCursor;
pCursor->right = pTemp;
pTemp->left = NULL;
pTemp->right = NULL;
return;
}
//If no, then iteravely continue.
else {
printf("Iteravely continuing to the right");
pCursor = pCursor->right;
continue;
}
}
//Is the value < the root?
else {
//DEBUG
printf("== check succeeded, now value < data\n");
//Is the value a Null?
if (pCursor->left == NULL) {
//DEBUG
printf("Running function to insert %d as a new node to the left\n", Value);
//If yes, then insert the value where the null is.
//Create Node
struct Node* pTemp = (struct Node*)calloc(1, sizeof(struct Node));
printf("Successfully declared and allocated memory");
pTemp->data = Value;
pTemp->parent = pCursor;
pCursor->left = pTemp;
pTemp->left = NULL;
pTemp->right = NULL;
return;
}
//If no, then iteravely continue
else{
printf("Iteravely continuing to the right");
pCursor = pCursor->left;
continue;
}
}
}
}
}
【问题讨论】:
-
struct Node* newNode = calloc(1, sizeof(binarySearchTree));看起来很奇怪,应该不是sizeof(Node)? -
值得注意的是,GeeksForGeeks 对二叉树进行了广泛的处理与源代码,以便您可以比较笔记。 geeksforgeeks.org/binary-tree-data-structure
-
您没有收到带有单独行
(*pBST).listRoot->data;的编译器警告吗?我建议你删除它...
标签: c memory struct heap-corruption