簡體   English   中英

使用迭代插入函數在第二次插入后初始化二叉搜索樹時出現分段錯誤

[英]Segmentation fault in inititalizing a binary search tree after second insertion using a iterative insert function

在嘗試將第二個節點插入樹后,我遇到了分段錯誤,拋出了分段錯誤。 是由於initialize函數還是insert導致的分段錯誤? 我如何通過在 server.c 中進行更改來解決它?

客戶端.c文件:

int main()
{
    Tree my_tree;
    initialize(&my_tree);
    while(1)
    {
        scanf("%d", &choice);
        switch (choice)
        {
        case 1:
            scanf("%d", &element);
            insert(&my_tree, element);
            break;
        case 2:
               exit(0);
       }
    }
    return 0;
}

server.c 文件


typedef struct node
{
    int data;
    struct node *left;
    struct node *right;
} Node;

typedef struct tree
{
    Node *root;
} Tree;

void initialize(Tree *tree)
{
    tree = (Tree*)malloc(sizeof(Tree));
    tree->root = NULL;
}

void insert(Tree *tree, int data)
{
    Node *temp = (Node*)malloc(sizeof(Node));
    temp->left = temp->right = NULL;
    temp->data = data;
    if(tree->root == NULL) 
        tree->root = temp;    
    else
    {
        Node *prev,*curr;
        prev = NULL;
        curr = tree->root;
        while(curr != NULL)
        {
            if(temp->data < curr->data){
                prev = curr;
                curr = curr->left;
            }
            if(temp->data >curr->data){
                prev = curr;
                curr = curr->right;
            }
        }
        if(temp->data < prev->data)
            prev->left = temp;
        if(temp->data > prev->data)
            prev->right = temp;
    }
}
void initialize(Tree *tree)
{
    tree = (Tree*)malloc(sizeof(Tree));
    tree->root = NULL;
}

改成

void initialize(Tree *tree)
{
    if (tree) {
     tree->root = NULL;
    }
}

當您為tree分配內存時,您將使其指向新的內存位置,因此您的原始tree的根節點不會被初始化為NULL並且您還會引入內存泄漏。

不是初始化您在程序中實際使用的Tree對象( main 中的tree ),而是分配一個新的Tree對象並初始化該對象。 實際上, initialize除了泄漏內存之外什么都不做。

要解決此問題,請更換

void initialize(Tree *tree)
{
    tree = (Tree*)malloc(sizeof(Tree));
    tree->root = NULL;
}

void initialize(Tree *tree)
{
    tree->root = NULL;
}

OP指出還有第二個錯誤。 在這里我指出一個人不應該依賴陌生人的好意,並學習如何調試此類問題。

您可以使用調試器。

$ gcc -Wall -Wextra -pedantic -g a.c -o a && gdb --args ./a
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
...
(gdb) r
Starting program: /tmp/ikegami/a
1
3
1
2

Program received signal SIGSEGV, Segmentation fault.
0x00005555555547b1 in insert (tree=0x7fffffffdda0, data=2) at a.c:39
39                  if(temp->data >curr->data){
(gdb) print temp
$1 = (Node *) 0x555555756690
(gdb) print curr
$2 = (Node *) 0x0
(gdb) quit
A debugging session is active.

        Inferior 1 [process 1433] will be killed.

Quit anyway? (y or n) y

另一種方法是在編譯程序時使用-fsanitize=address

$ gcc -Wall -Wextra -pedantic -g -fsanitize=address a.c -o a && ./a
1
3
1
2
ASAN:DEADLYSIGNAL
=================================================================
==1370==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x556253e76e87 bp 0x7ffe3a28e390 sp 0x7ffe3a28e360 T0)
==1370==The signal is caused by a READ memory access.
==1370==Hint: address points to the zero page.
    #0 0x556253e76e86 in insert /home/ikegami/tmp/a.c:39
    #1 0x556253e771af in main /home/ikegami/tmp/a.c:64
    #2 0x7fc3bdadcb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #3 0x556253e76b29 in _start (/tmp/ikegami/a+0xb29)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/ikegami/tmp/a.c:39 in insert
==1370==ABORTING

但是方法表明temp->data >curr->data是罪魁禍首。 使用調試器,我們看到currNULL ,所以curr->data是有問題的。 現在您知道您需要弄清楚為什么curr在您不希望它是 NULL 時為 NULL。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM