简体   繁体   中英

Why is this segfaulting whilst building a binary tree?

I have found this line in this code through gdb to be seg faulting. However I can't seem to see why? It will run through 6/7 times before a seg fault occurs. 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.

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 . You must check its not null before trying to access it's memebers.

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:

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.

(I don't like the name temp so I've changed it to node in my examples)

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 . 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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