用于在C中为二叉搜索树分配内存的分段错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于在C中为二叉搜索树分配内存的分段错误相关的知识,希望对你有一定的参考价值。
我试图在C中实现二进制搜索树,并在尝试运行我的代码时遇到分段错误。基本上在我的代码中,我正在读取文件中的一行数据,为它创建一个节点,然后将其插入到我的二叉搜索树中。我甚至不确定我的代码实现是否正确,因为当我尝试运行它时,我遇到了分段错误。我对C编程很新,特别是分配内存,所以我知道我的代码中可能存在大量错误,即使在代码本身的核心结构中也是如此。因此,任何帮助找到分段错误背后的原因或帮助代码本身的核心结构将是值得赞赏的。
您的代码中存在多个问题:
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;
}
这可能更多的是评论而不是答案,但我没有足够的“声誉”来评论,所以...
这个问题与指针的使用有关,而不是像@Lundin先前评论的那样。
在这一行:*node->left = insertNode(node->left, newNode);
node-> left可以为NULL。在对insertNode的调用中,检查这个并将newNode分配给node-> left的本地副本,但这对node-> left没有影响,所以当insertNode的返回值写入节点指向的位置时-left(NULL),你有一个保证崩溃!
你可以自由地指向你的堆栈:
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
中的根节点
编辑:这是malloc的语法:
bst_t *root = malloc(sizeof(bst_t));
malloc
函数返回指向新分配空间的指针,并将分配的大小作为参数。
旁注:如果你想要真的很干净,如果没有可用的记忆(非常罕见),malloc
可以返回null
,所以检查返回是一个好习惯。
more info
我认为问题出在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.确保释放堆上分配的所有内存,并且不要错误地释放堆栈上分配的内存,就像您在此处所做的那样。
以上是关于用于在C中为二叉搜索树分配内存的分段错误的主要内容,如果未能解决你的问题,请参考以下文章