简体   繁体   English

为什么在构建二叉树时出现此段错误?

[英]Why is this segfaulting whilst building a binary tree?

I have found this line in this code through gdb to be seg faulting. 我发现通过gdb在此代码中的这一行是seg错误。 However I can't seem to see why? 但是我似乎看不出为什么? It will run through 6/7 times before a seg fault occurs. 在发生段故障之前,它将运行6/7次。 Temp is a node in a linked list which contains a frequency (int), which I use to find the place in an ascending linked list to insert a new node. Temp是链表中的一个节点,其中包含一个频率(int),我用它在升序链表中查找插入新节点的位置。

while (ind == 0 && temp != NULL)
{
    temp = temp -> next;
    if (temp -> frequency > parent_node -> frequency) /*<--- SEG FAULT HERE */
    {
        parent_node -> next = temp -> next; /* parent points at higher freq node */ 
        temp -> next = parent_node; /* parent node is temp next */
        ind = 1;
    }
    if (temp -> next == NULL)
    {
        temp -> next = parent_node; 
        ind = 1;          
    }
}

You do temp = temp->next but temp->next might be nullptr . 您执行temp = temp->next但是temp->next可能为nullptr You must check its not null before trying to access it's memebers. 您必须先检查它的非null才能尝试访问它的成员。

Here is some code which will insert a new node pointed to by newnode into a linked list where liststart points to the first node in the list or is NULL for an empty list: 这是一些代码,它将由newnode指向的新节点插入到链表中,其中liststart指向列表中的第一个节点,或者对于空列表为NULL

if (liststart == NULL) {
    liststart = newnode;
    newnode->next = NULL;
} else {
    struct mylist *prev = liststart;

    while (prev->next != NULL && prev->next->frequency <= newnode->frequency) {
        prev = prev->next;
    }
    if (prev->next == NULL) {
        prev->next == newnode;
        newnode->next = NULL;
    } else {
        newnode->next = prev->next->next;
        prev->next = newnode;
    }
}

Here's an alternate version that uses pointers to pointers: 这是使用指针的替代版本:

struct mylist **pprev;

pprev = &liststart;
while (*pprev != NULL && (*pprev)->frequency <= newnode->frequency) {
    pprev = &(*pprev)->next;
}
newnode->next = *pprev;
*pprev = newnode;

Your issue is that you check that temp isn't null, then immediately update temp , so it may be null again. 您的问题是您检查temp不为null,然后立即更新temp ,因此它可能又为null。

(I don't like the name temp so I've changed it to node in my examples) (我不喜欢temp这个名字,因此在示例中将其更改为node

It's clearest if you decompose it, so: 如果分解,这是最清楚的,因此:

while(ind == 0 && node != null) {
     node = node -> next;  // now node might be null
     doStuffWith(node);
}

Instead, you could move the assignment to the end of the loop. 相反,您可以将分配移到循环的末尾。 That means, of course, that the first time around, the assignment hasn't happened. 当然,这意味着第一次没有分配。 So you may need to call it once outside the loop: 因此,您可能需要在循环外调用一次:

node = node -> next; // or some other initialisation of node
while(ind == 0 && node != null) {
     doStuffWith(node);
     node = node -> next;
}

Maybe you've been told about the DRY principle: "Don't repeat yourself", so you might feel uncomfortable about repeating node = node -> next . 也许您已经被告知DRY原理:“不要重复自己”,所以对于重复node = node -> next可能会感到不舒服。 However it's an example of a very common pattern, for example: 但是,这是一个非常常见的模式的示例,例如:

int chars = stream.read(buffer);
while(chars != -1) {
     doSomethingWith(buffer);
     chars = stream.read(buffer);
}

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

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