所以我是一名Python程序员,我正在努力自学C。作为实践,我一直在尝试在C中实现一个简单的二进制搜索树。我以前从未使用过内存分配或指针,这导致了很多错误。
我的程序一直在给我退出代码-103740940(0xC0000374(,我知道这意味着堆已经损坏。这是一个有点长的程序,所以我只是包含了冒犯性的函数。
使用for循环重复调用此插入函数,将数组的内容插入到二进制搜索树中。数组的内容为5、4、6、3、7、2、8、1、9和0(旨在使树平衡(。
因此,函数首先有5个传递给它。pBST->listRoot为NULL(pBST是指向列表结构的指针(,因此插入5作为根节点。这很好用。然后4被传递给函数。由于已经有一个根,它会检查该根的子级。4小于5,所以检查5的左子项。5的左子节点的指针为null,因此它尝试插入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 > datan");
// Is the value a Null?
if (pCursor->right == NULL) {
//DEBUG
printf("Running function to insert %d as a new node to the rightn", 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 < datan");
//Is the value a Null?
if (pCursor->left == NULL) {
//DEBUG
printf("Running function to insert %d as a new node to the leftn", 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* pTemp = calloc(1, sizeof(binarySearchTree));
是错误的。结构binarySearchTree
有一个指针和一个int
,但结构struct Node
有4个指针,因此struct Node
应该大于binarySearchTree
,并且这种分配将分配比所需更少的空间,导致超范围访问。
应该是:
struct Node* pTemp = calloc(1, sizeof(*pTemp));
或
struct Node* pTemp = calloc(1, sizeof(struct Node));
此外,将数据int Value
与(*pBST).listRoot->data = Value;
一起存储在成员int* data;
中看起来非常奇怪。看起来成员应该是int
,而不是int*
。