0

following some forums and tutorials I wrote a code for sorted linked list. The code is causing core dump. I believe error is after line 50 where I'm trying to insert node at the end. Can you please help me with the bug? I'm not sure what I'm doing wrong. Thanks.

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

struct node
{
    char val;
    struct node* next;
};

struct node *start = (struct node*) NULL;

// definition of creating only first node
struct node* create(char* data)
{
    struct node* temp;
    temp = (struct node*)malloc(sizeof(struct node));
        if (start == NULL)
        {
            temp->val = data;
            temp->next = NULL;
            start = temp;
        }
    printf("List created\n");
}

struct node* insert(char* data)
{
    int i, pos;
    struct node* tempnode, *ptr;
    ptr = start;

    while(ptr != NULL)
    {
        if (data <= ptr->val)
        {
            printf("!!!Inserting before!!!\n");
            tempnode = (struct node*)malloc(sizeof(struct node));
            tempnode->val = ptr->val;
            tempnode->next=ptr->next;
            ptr->val = data;
            ptr->next=tempnode;
            break;
        }
        else if (data > ptr->val)
        {
            printf("!!!Going next!!!\n");
            ptr = ptr->next;
        }
        if (ptr == NULL) //insert behind the node
        {
            tempnode = (struct node*)malloc(sizeof(struct node));
            tempnode->val = data;
            tempnode->next = NULL;
            ptr->next = tempnode;
            printf("!!!Placed at the end!!!\n");
            break;
        }
    }
}

void display()
{
    struct node* ptr; // ptr is pointer
    ptr = start;
    while (ptr != NULL)
    {
        printf("%s->", ptr->val);
        ptr = ptr->next;
    }
    printf("End of list\n");
}

int main()
{
    char* data;
    int i = 0;

    create(0);
    FILE* file = fopen("words.txt", "r");

    while (i < 10)
    {
        fscanf(file, "%s", &data);
        printf ("data is %s\n", &data);
        insert(data);
        i++;
    }
    display();

}
2
  • 1
    Build your program with debug information (add the -g flag to GCC), and run it in a debugger. The debugger will stop at the exact location of the crash, and let you see both the function call stack and let you examine values of variables. You should at least get the function call stack, and edit your question to include it. Commented Mar 28, 2014 at 12:14
  • Also your functions create and insert don't return anything, but should Commented Mar 28, 2014 at 12:22

5 Answers 5

2

Here, at the bottom of your insert function, you have guaranteed that ptr is NULL, but yet you do ptr->next = .... This is equivalent to (*ptr).next = ... which dereferences a NULL pointer!

if (ptr == NULL) //insert behind the node
    {
        tempnode = (struct node*)malloc(sizeof(struct node));
        tempnode->val = data;
        tempnode->next = NULL;
        ptr->next = tempnode;
        printf("!!!Placed at the end!!!\n");
        break;
    }
Sign up to request clarification or add additional context in comments.

Comments

2

Local variables are never initialized, their values are indeterminate (and will seem to be random). Using uninitialized local variables leads to undefined behavior.

Now look at the data variable in the main function: It's uninitialized, and therefore can't be used until you actually make it point somewhere. Since you don't do that you have undefined behavior. You also use it wrongly in the fscanf call, as you pass the address of the pointer to fscanf. While the arguments should be pointers, data already is a pointer. You just need to allocate memory for it. This is simplest done by making it an array instead of a pointer:

char data[128];

There are also some other problems, like you using the comparison operators like <= to compare strings. This will only compare the pointers. Use strcmp to compare strings. Another problem is that even when you fix the above, it will not work as you expect, and that is because you use the same string pointer for all nodes. You need to duplicate the strings when you add nodes. This can be done with the strdup function:

ptr->val = strdup(data);

Of course, since this allocates memory for the string using malloc, you have to free this memory manually.

1 Comment

He also needs to pass data and not &data to scanf.
0

My first observation is that you have not allocated memory to char* data in main. This way you are corrupting the memory when doing fscanf(file, "%s", data);. Also you would like to dynamically allocate/deallocate this memory not like char data[128], since you want each node to have different data.

Comments

0

There are a number of problems with this code. Does it compile without warnings? Does it compile at all?

  • In main(), you haven't initialized data before using it. Most compilers will warn you about that.

  • create() and insert() both say they return struct node* but do not return anything. The compiler should complain about that.

  • insert() takes char *data as a parameter, but you assign tmpnode->val = data in that function. According to your declaration of struct node, val is a char, not a char *. The compiler should complain about that too.

  • In main(), data is a char *, and you are passing the address of the pointer into fscanf(). And you haven't allocated any memory for data, nor initialized it to anything non-random, so you are passing the address of a bogus pointer into fscanf().

There's lots more, but that's a good start. If you've disabled warnings in your compiler, enable them agian - they're telling you something important. If you are getting warnings and ignoring them, stop ignoring them - they are telling you something important.

Comments

0

I pretty much reworked the code from scratch and I'm sure there are probably still many things to fix but it does sort the input. Only thing which bothers me is that Valgrind throws out plenty of errors for my Freememory function

HEAP SUMMARY:
==8731==     in use at exit: 0 bytes in 0 blocks
==8731==   total heap usage: 9 allocs, 32 frees, 1,016 bytes allocated
==8731== 
==8731== All heap blocks were freed -- no leaks are possible
==8731== 
==8731== For counts of detected and suppressed errors, rerun with: -v
==8731== ERROR SUMMARY: 38 errors from 6 contexts (suppressed: 2 from 2)

Anyway my solution to the problem is here:

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// maximum length for a word
#define LENGTH 45

// default dictionary
#define DICTIONARY "words.txt"

typedef struct node
{
    char word[LENGTH + 1];
    struct node* next;
}
Word;

Word *head = NULL; //start
Word *cur = NULL;  //cursor
Word *cur2 = NULL;  //cursor

/****************************************/
/*              PROTOTYPES              */
/****************************************/
Word* create(char *node);
void display();
void freememory();

/****************************************/
/*              FUNCTIONS               */
/****************************************/

Word* create(char *node)
{
    Word *new_node = NULL;
    new_node = (Word*)malloc(sizeof(Word));
    strncpy(new_node->word, node, LENGTH);

    if(head==NULL)
    {
        head=new_node;
        new_node->next=NULL;
    }
    else
    {
        cur = head;
        cur2 = cur->next;
        while (cur != NULL)
        {
            if (strcmp(new_node->word, cur->word) > 0 )
            {

                if (cur->next == NULL)
                {
                    new_node->next = NULL;
                    cur->next = new_node;
                    break;
                }
                else if (strcmp(new_node->word, cur->word) > 0 && strcmp(new_node->word, cur2->word) <= 0)
                {
                    new_node->next = cur->next;
                    cur->next = new_node;
                    break;
                }
            }
            else if (strcmp(new_node->word, cur->word) <= 0 )
            {
                new_node->next = head;
                head = new_node;
                break;
            }
            cur = cur->next;
            cur2 = cur2->next;
        }
    }
    return head;
}

// output the list
void display()
{
    //Word *Wordlist;
    cur = head;
    while (cur != NULL)
    {
        printf("%s->", cur->word);
        cur = cur->next;
    }
    printf("End of the list!\n");
}

// free allocated memory
void freememory()
{
    Word *temp = NULL;
    Word *temp2 = NULL;
    cur = head;
    cur2 = head;
    while(cur != NULL)
    {
        temp = cur;
        cur = cur->next;
        free(cur);
        free(temp);
    }

    while(cur2 != NULL)
    {
        temp2 = cur2;
        cur2 = cur2->next;
        free(cur2);
        free(temp2);
    }

    free(head);
}

/****************************************/
/*               M A I N                */
/****************************************/

int main()
{
    system("clear");
    char data[LENGTH];

    FILE* file = fopen(DICTIONARY, "r");

    // check successful opening of the file
    if(file == NULL) {
        perror("Error opening file");
        return -1;
    }

    //read data (words) from file
    while(fscanf (file, "%s", data) == 1)
    {
        create(data);
    }
    display();
    freememory();
    fclose(file);
    return 0;
}

1 Comment

Your freememory() function is broken. You spin through the list twice (why?) and free each node and its ->next pointer on each iteration. Think about what happens there...

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.