0

I've written an implementation of a doubly linked list with a .h prototype here and everything runs fine until I start entering values in the terminal. I get a segmentation fault after entering the second value, but, if I just use 1 value it executes normally. I've gone through it several times, but, I can't find my mistake. Could you guys help me find why I'm getting the error?

Here's the .h file:

#include <stdio.h>
typedef struct node Node;

struct node
{
    int d;
    Node *link;
}*head,*current,*prev;

int num_nodes;

void linked_list_init(int data);
void linked_list_sort();
void linked_list_print();

And here's the .c file:

#include "link.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

void main(){

    int n,e,i;
    printf("How many numbers do you want to sort: ");
    scanf("%d",&e);
    for(i=0;i<e;i++){
        printf("Enter number: ");
        scanf("%d",&n);
        linked_list_init(n);
    }
    linked_list_sort();
    printf("The sorted numbers are: ");
    linked_list_print();
}

void linked_list_init(int data){
    Node *prev=0,*next=0;

    current=(Node*)malloc(sizeof(Node));    
    if(head==0)
    {
        head=current;
        current->d=data;
        current->link=0;
        prev=current;

    }
    else{
        current->d=data;
        current->link=0;
        prev->link=current;
        prev=current;
    }
    }

void linked_list_sort(){
    int i,j;
    Node *prev=0,*next=0;

    current=head;
    prev=head;
    next=head->link;

    for(i=0;i<num_nodes-1;i++)
    {
        for(j=0;j<num_nodes-i-1;j++)
        {
            if(current->d>next->d)
            {
                current->link=next->link;
                next->link=current;
                if(current==head)
                {
                    head=next;prev=next;
                }
                else
                {
                    prev->link=next;prev=next;
                }
                if(next!=0) //check whether final node is reached
                    next=current->link;

            }
            else //move each node pointer by one position
            {
                prev=current;
                current=next;
                next=current->link;
            }

        }
        //next iteration
        current=head;
        prev=head;
        next=current->link;
    }

}

void linked_list_print(){
    current=head;
    while(current!=0){
        printf("%d ",current->d);
        current=current->link;
    }
}
0

4 Answers 4

5

The problem is that you're masking the global variables with local declarations in your function. That means that the variable prev in the functions are not the same as the global variable prev.

Aside from that, you should never place variable definitions in header files, as those will clash with each other if the header file is included in multiple files.

There is also another small bug, in that you don't increase the counter when inserting a new node into the list.

Sign up to request clarification or add additional context in comments.

5 Comments

Also OP is checking head==0 shouldn't it be head==NULL ?
@BhavikShah Often in C, NULL is a macro (#define) that resolves to ((void *) 0). This was relaxed in C++ where NULL is almost never used instead of using 0 directly.
@JoachimPileborg: Say what? if(head == NULL) is easier to read than if(head == 0). And if you prefer shorter code, you'd probably be doing if(head) anyway.
@JoachimPileborg: Global variables are auto-initialized to zero as part of the ELF and PE file specifications, but you're right, Robert should be initializing them to avoid a NULL dereference segfault.
@SecurityMatt You're right about the initialization of global variables. I always seem to forget that. :)
1

There is no need to initialize head to 0 because in your case you have declared it globally in header file ( although its not a good practice to declare variables in header files). The problem here is you are redefining prev node in void linked_list_init(int data) function. Just delete the prev node from there and everything would work fine.

Tips:

-> Declare the head, prev, current nodes in .c file.

-> Use NULL instead of 0 or even you can use (void *) 0 instead of simply 0

Comments

0

It seems like you are creating and initializing *prev and *current everytime the linked_list_init function is called. Hence after you enter the second value, the second if loop is using prev, which has actually been set to 0.

I think what you are trying to do is use the *prev, *head and *current as global variables (since you have declared them in your header file). Just use extern to declare them in the source file and things should work.

Comments

0

The global variable used in your program are uninitialized and hence prone to garbage values . Also i suggest the following defination for your node

struct node {
    int d;
    node *llink; // Left Link
    node *rlink; // Right Link
};
typedef struct node* Node;
Node head = NULL; // Head node 

Also

void linked_list_init(int data) {

    Node newnode = (Node) malloc(sizeof (Node));
    newnode->d = data;

    Node curr;

    if (head == NULL) {

        newnode->llink = NULL;
        newnode->rlink = NULL;
        head = newnode;

    } else {
        curr = head;
        while (curr->rlink) {
            curr = curr->rlink;
        }
        curr->rlink = newnode;
        newnode->rlink = NULL;
        newnode->llink = curr;       
    }
}

The above will keep adding elements to the end of the list .

You can print data out easily as follows :

void linked_list_print() {
    Node curr;
    curr = head;
    while (curr) {
        printf("Element Data : %d", curr->d);
        curr = curr->rlink;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.