用于在C中为二叉搜索树分配内存的分段错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于在C中为二叉搜索树分配内存的分段错误相关的知识,希望对你有一定的参考价值。

我试图在C中实现二进制搜索树,并在尝试运行我的代码时遇到分段错误。基本上在我的代码中,我正在读取文件中的一行数据,为它创建一个节点,然后将其插入到我的二叉搜索树中。我甚至不确定我的代码实现是否正确,因为当我尝试运行它时,我遇到了分段错误。我对C编程很新,特别是分配内存,所以我知道我的代码中可能存在大量错误,即使在代码本身的核心结构中也是如此。因此,任何帮助找到分段错误背后的原因或帮助代码本身的核心结构将是值得赞赏的。

答案

您的代码中存在多个问题:

  • rootmain函数中未初始化。它必须在传递给NULL之前初始化为insertNode()
  • 你应该只解析readdata()中的一行并返回一个成功指标。
  • 你应该在main循环中迭代,直到readdata无法从文件中读取更多记录。您当前的测试while ((c = getchar()) != EOF)是不合适的,并破坏此输入流。

以下是readdatamain函数的修改版本:

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中为二叉搜索树分配内存的分段错误的主要内容,如果未能解决你的问题,请参考以下文章

将空二叉树填充为二叉搜索树而不改变结构(节点链接)

LeetCode 108. 将有序数组转换为二叉搜索树

LeetCode-108. 将有序数组转换为二叉搜索树

给定二叉树是不是为二叉搜索树

|二叉树|669. 修剪二叉搜索树 |108.将有序数组转换为二叉搜索树|538.把二叉搜索树转换为累加树

⭐算法入门⭐《二叉树 - 二叉搜索树》简单03 —— LeetCode 108. 将有序数组转换为二叉搜索树