我正在尝试在C中实现二进制搜索树,并且在尝试运行我的代码时遇到分段错误。本质上,在我的代码中,我从文件中读取一行数据,为其创建一个节点,然后将其插入到我的二进制搜索树中。我什至不确定我的代码实现是否正确,因为在尝试运行它时遇到了段错误。我对C编程(尤其是分配内存)非常陌生,因此我知道我的代码中甚至在代码本身的核心结构中可能存在大量错误。这样,对找出分段错误背后的原因的任何帮助或对代码本身的核心结构的帮助将不胜感激。
答案 0 :(得分:1)
这可能是评论而不是答案,但是我没有足够的“声誉”来评论,所以...
这个问题与指针的使用有关,而不是@Lundin先前评论的。
在此行中:
*node->left = insertNode(node->left, newNode);
node-> left可以为NULL。在对insertNode的调用中,您需要进行检查并将newNode分配给node-> left的本地副本,但这对node-> left无效,因此在写入insertNode的返回值时到节点左(NULL)所指向的位置,您肯定会崩溃!
答案 1 :(得分:0)
您可以释放指向堆栈的指针:
int main(int argc, char *argv[]) {
bst_t root; <<< root is allocated on stack
bst_t newNode;
int c;
while ((c = getchar()) != EOF){
newNode = createNode();
root = insertNode(&root,&newNode);
}
freeTree(&root); <<< Your are passing a pointer to root ( pointer to a stack element )
return 0;
}
void freeTree(bst_t *parent){ <<< parent is a pointer to a stack element
if(! parent){
return;
}
freeTree(parent->left);
freeTree(parent->right);
free(parent); <<< you free a stack element => segmentation fault
}
您必须分配根节点以便可以释放它,或者在您的freeTree
中处理根节点
编辑:这是对其进行分配的语法:
bst_t *root = malloc(sizeof(bst_t));
malloc
函数返回指向新分配空间的指针,并将分配大小作为参数。
旁注:如果您真的想清除它,如果没有可用的内存,malloc
可以返回null
(非常少),因此,检查返回是一种很好的做法。 br />
more info
答案 2 :(得分:0)
我认为问题出在readData
函数中。使用scanf
时,必须使用地址运算符&
读取变量。
以下代码:
void readData(bst_t *node) {
while (scanf("%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],"
"%[^,],%[^,],%[^,],%[^,],%[^,]",
node->data.ID, node->data.name, node->data.sex,
node->data.height, node->data.weight, node->data.team,
node->data.NOC, node->data.games, node->data.year,
node->data.season, node->data.city, node->data.sport,
node->data.event, node->data.medal) == 14) {
continue;
}
应更改为:
void readData(bst_t *node) {
while (scanf("%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],"
"%[^,],%[^,],%[^,],%[^,],%[^,]",
&node->data.ID, &node->data.name, &node->data.sex,
&node->data.height, &node->data.weight, &node->data.team,
&node->data.NOC, &node->data.games, &node->data.year,
&node->data.season, &node->data.city, &node->data.sport,
&node->data.event, &node->data.medal) == 14) {
continue;
}
还应进行一些修改:
1.使用指向结构而不是结构的指针传递参数和返回值。
2.在处理链接列表时(甚至对于根节点),在堆上而不是在栈上分配内存。
3.在堆上分配内存时,请确保分配的大小是结构的大小,而不是结构的指针的大小。
4.确保释放了分配在堆上的所有内存,并且不要错误地释放似乎在此处执行的分配在堆栈上的内存。
答案 3 :(得分:0)
您的代码中存在多个问题:
root
在main
函数中未初始化。在将其传递给NULL
之前,必须将其初始化为insertNode()
。
您应该只解析readdata()
中的一行并返回成功指示符。
您应该在main
循环中进行迭代,直到readdata
无法从文件中读取更多记录。您当前的测试while ((c = getchar()) != EOF)
不适当,并且破坏了此输入流。
以下是readdata
和main
函数的修改版本:
bst_t *createNode(void) {
bst_t *newNode;
newNode = (struct bst_t *)malloc(sizeof(struct bst_t));
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
int readData(bst_t *node) {
return scanf("%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],"
"%[^,],%[^,],%[^,],%[^,],%[^,]",
node->data.ID, node->data.name, node->data.sex,
node->data.height, node->data.weight, node->data.team,
node->data.NOC, node->data.games, node->data.year,
node->data.season, node->data.city, node->data.sport,
node->data.event, node->data.medal) == 14;
}
int main(int argc, char *argv[]) {
bst_t *root = NULL;
bst_t *newNode;
while ((newNode = createNode()) != NULL) {
if (readData(newNode)) {
/* record was read correctly: insert into the tree */
root = insertNode(root, newNode);
} else {
/* end of file or input error: stop reading the file */
free(newNode);
break;
}
}
freeTree(root);
return 0;
}