简体   繁体   English

分段错误错误 - C 中的二叉搜索树

[英]Segmentation Fault error - binary search tree in C

I'm trying to build a binary search tree.我正在尝试构建二叉搜索树。 Inserting an integer using insert function (only using 1 to 100 for testing) and appending the result to a file using inorder traversal.使用插入 function 插入 integer(仅使用 1 到 100 进行测试)并使用中序遍历将结果附加到文件中。 However, i'm getting a segmentation fault error.但是,我遇到了分段错误错误。 Using Visual Studio code on Macbook Pro 2020. Also tested on Codeblocks on Windows - filename.exe stops working and crashes.在 Macbook Pro 2020 上使用 Visual Studio 代码。还在 Windows 上的代码块上进行了测试 - filename.exe 停止工作并崩溃。

#include <stdio.h>
#include <stdlib.h>
    
typedef struct node *BST;
    
struct node {
    int data;
    BST left;
    BST right;
};

BST insert(BST root, int number) {
    BST temp = NULL;
    if (root == NULL) {
        temp = *(BST *)malloc(sizeof(BST));
        temp->left = NULL;
        temp->right = NULL;
        temp->data = number;
        root = temp;
        }
    else if (root->data > number) {
        insert(root->left, number);
    }
    else {
        insert(root->right, number);
    }
    return root;
}

//returning null if number not found and pointer to root if found
BST find(BST root, int number) {
    if (root == NULL) {
        return NULL;
    }
    
    if (root->data > number) {
        find(root->left, number);
    }
    else if (root->data < number) {
        find(root->right, number);
    }
    else (root->data = number);
        return root;
}
    
//printing number to file
void inOrder (BST root, FILE *fp) {
    if (root == NULL) return;
    inOrder(root->left, fp);
    fprintf(fp, "%d", root->data);
    inOrder(root->right, fp);
}

int main() {
    BST root = NULL;
    int n = 100;
    int treeArray[n];
    for (int r = 0; r < n; r++) {
        treeArray[r] = r;
    }
    root = insert(root, treeArray[0]);
    for (int x = 1; x < n; x++) {
        insert(root, treeArray[x]);
    }
    
    FILE *treefile = fopen("print_tree.txt", "w");
    inOrder(root, treefile);
    fclose(treefile);
    return 0;
}
    
Error: /bin/sh: line 1: 44278 Segmentation fault: 11 *file path redacted*

What am I doing wrong here?我在这里做错了什么? :( :(

You declare BST as:您将BST声明为:

typedef struct node *BST;

So, it is a pointer to a struct node and your problem is probably here:所以,它是一个指向struct node的指针,你的问题可能在这里:

temp = *(BST *)malloc(sizeof(BST));
  1. You are allocating memory but the byte size you specified is that of BST , that is pointer to struct node , while you want to allocate a struct node .您正在分配 memory 但您指定的字节大小是BST的字节大小,即指向struct node的指针,而您要分配一个struct node

  2. You cast the returned value of malloc to a pointer to a BST , that is, a pointer to a pointer to a struct node .您将malloc的返回值转换为指向BST的指针,即指向struct node的指针的指针。 And then you de-reference it to assign the result to temp .然后您取消引用它以将结果分配给temp So, what you assign to temp is a pointer to a struct node (correct) but the pointed object has the wrong size.因此,您分配给temp的是指向struct node的指针(正确),但指向的 object 的大小错误。 Anyway, you should not cast the value returned by malloc ( void * ) .无论如何, 您不应该malloc ( void * ) 返回的值

Things are much simpler than you apparently think: if you want to allocate a struct node (or anything else) pass its size to malloc .事情比你想象的要简单得多:如果你想分配一个struct node (或其他任何东西),请将其大小传递给malloc malloc returns a void * pointer to the allocated struct node that you can assign to any pointer variable without casting. malloc返回一个指向已分配struct nodevoid *指针,您可以将其分配给任何指针变量而无需强制转换。

Note: you should check the returned value because if malloc fails it returns NULL and you should not use that.注意:您应该检查返回的值,因为如果malloc失败,它会返回NULL并且您不应该使用它。

Try this, instead:试试这个,而不是:

temp = malloc(sizeof (struct node));
if(temp == NULL) {
  fprintf(stderr, "%s:%d allocation failed\n", __FILE__, __LINE__);
  exit(EXIT_FAILURE);
}

I assumed that an allocation error, in your case, is unrecoverable, adapt if it is.我假设在您的情况下分配错误是不可恢复的,如果是,请调整。

Note: you could also, as suggested in comments, use:注意:您也可以按照评论中的建议使用:

temp = malloc(sizeof *temp);

which will always work, by construction.通过施工,这将始终有效。 But as long as you are not completely comfortable with pointers and memory allocation I suggest that you use explicit types with malloc .但只要您对指针和 memory 分配不完全满意,我建议您使用带有malloc的显式类型。 It is a bit easier to read and understand, even if it is a bit less easy to maintain (if you change the type of temp ).它更容易阅读和理解,即使它不太容易维护(如果你更改temp的类型)。

But there are other problems with your code.但是您的代码还有其他问题。 Your insert and find functions are bogus.您的insertfind功能是伪造的。 Understanding why is left as a debugging exercise.理解为什么留作调试练习。

Main problem is with this statement:主要问题在于此声明:

temp = *(BST *)malloc(sizeof(BST));

As it was already explained in the other answer clearly, I am going to skip that.正如其他答案中已经清楚解释的那样,我将跳过它。

So you can do:所以你可以这样做:

temp = malloc(sizeof (struct node));

OR或者

// to add : this helps in case the type of temp ever changes,
temp = malloc(sizeof(*temp));

Other minor logical changes:其他小的逻辑变化:

  • In the find function, there is no need of this else if statementfind function中,不需要这个else if语句
    // = or == doesn't matter now
    else (root->data = number);
  • In the insert function, you forgot to link the nodes which you insert after your root node.insert function 中,您忘记链接在根节点之后插入的节点。 So whenever you perform the inorder traversal , you only get the root node ie 0 in your case.因此,每当您执行中inorder traversal时,您只会得到根节点,即0在您的情况下。

Note:笔记:

typedef is used to make code more readable, but hiding the pointer using typedef creates confusion. typedef用于使代码更具可读性,但使用 typedef 隐藏指针会造成混乱。 So I would suggest not to typedef pointers.所以我建议不要 typedef 指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM