1

I have to write this code that makes a linked list. The following code is below. The problem is that I am segfaulting somewhere in the code and I can't figure out where. If anyone could help me find and understand (that's the most important part) where the segfault is coming from, it would be greatly appreciated.

#include "linkedlist.h"
#include <stdio.h>
#include <stdlib.h>


/* Alloc a new node with given data. */
struct ListNode* createNode(int data) {
    struct ListNode *new_node = (struct ListNode *)malloc(sizeof(struct ListNode));
    new_node->data = data;
    new_node->next = NULL;
    return new_node;
}

/* Insert data at appropriate place in a sorted list, return new list head. */
struct ListNode* insertSorted(struct ListNode* head, int inputData)
{

    struct ListNode * nextIS = NULL;
    struct ListNode * newNodeIS = NULL;
    struct ListNode * currIS = head;
    struct ListNode * listHeadIS = currIS;
    if (currIS == NULL)
    {
        listHeadIS = createNode(inputData);
        return listHeadIS;
    }
    while (currIS->next != NULL)
    {
        nextIS = currIS->next;

        if (currIS->data < inputData)
        {
            if (nextIS->data >= inputData)
            {

                nextIS->next = createNode(inputData);
                newNodeIS = nextIS->next;
                if (newNodeIS->data > listHeadIS->data)
                {
                    listHeadIS = newNodeIS;
                }
            }
        }
        currIS = currIS->next;
    }

    return listHeadIS;
}
/* Remove data from list pointed to by headRef, changing head if necessary.
 * Make no assumptions as to whether the list is sorted.
 * Memory for removed node should be freed.
 * Return 1 if data was present, 0 if not found. */
int removeItem(struct ListNode** headRef, int data)
{
    while (*headRef && (*headRef)->data != data)
        headRef = &(*headRef)->next;

    if (*headRef)
    {
        struct ListNode *tmp = *headRef;
        free(tmp);
        *headRef = tmp->next;

        return 1;
    }
    return 0;
}

/* Insert data at head of list, return new list head. */
struct ListNode* pushStack(struct ListNode* head, int data)
{
    int dataPush = data;

    struct ListNode * tempPush = (struct  ListNode*)malloc(sizeof(struct ListNode));
    tempPush->data = dataPush;
    tempPush->next = head;
    *head = *tempPush;
    return tempPush;
}

/* Remove and return data from head of non-empty list, changing head.
 * Memory for removed node should be freed. */
int popStack(struct ListNode** headRef)
{
    struct ListNode * tempPop = *headRef;
    int tempData;

    free(tempPop);
    tempData = tempPop->data;
    tempPop = tempPop->next;

    return tempData;
}

/* Return length of the list. */
    int listLength(struct ListNode* head)

 {
   int count = 0;
    struct ListNode* current = head;
    while (current != NULL) {
    count++;
    current=current->next;
  }
   return(count);
}

/* Print list data on single line, separated with spaces and ending
 * with newline. */
void printList(struct ListNode* head)
{

    if (head != NULL)
    {

        while (head->next != NULL)
        {

            printf("%d\n", head->data);
            head = head->next;
        }
    }
}
/* Free memory used by the list. */
void freeList(struct ListNode* head)
{
    struct ListNode* tmp;

    while (head != NULL)
    {
        tmp = head;
        head = head->next;
        free(tmp);
    }
}

/* Reverse order of elements in the list */
void reverseList(struct ListNode** headRef)
{
    struct ListNode * origRL = *headRef;
    struct ListNode * nextRL = NULL;
    struct ListNode * prevRL = NULL;
    while (origRL->next != NULL);
    {
        nextRL = origRL->next;
        prevRL = origRL;
        origRL = nextRL;
        origRL->next = prevRL;
   }

}

The file used to test it (linkedlist.c) is included below this comment.

#include <stdio.h>
#include <stdlib.h>
#include "linkedlist.h"

int main(int argc, char** argv)
{
  int i, n;
  struct ListNode* head = NULL;
  struct ListNode* stack = NULL;

  printf("empty list: ");
  printList(head);

  for(i = 0; i < 23; ++i)
  {
    n = (i*17+11) % 23;
    head = insertSorted(head, n);
    stack = pushStack(stack, n);
  }

  printf("filled list: ");
  printList(head);
  printf("list length = %d\n", listLength(head));

  printf("filled stack: ");
  printList(stack);
  printf("stack size = %d\n", listLength(stack));

  for(i = -4; i < 25; i+=4)
  {
    n = removeItem(&head, i);
    if(!n) printf("remove did not find %d\n", i);  
  }

  printf("list after removes: ");
  printList(head);
  printf("list length = %d\n", listLength(head));

  for(i = 0; i < 5; ++i)
  {
    printf("pop: %d\n", popStack(&stack));
  }

  printf("stack after pops: ");
  printList(stack);
  printf("stack size = %d\n", listLength(stack));

  reverseList(&head);
  printf("list after reverse: ");
  printList(head);

  freeList(head);
  head = NULL;

  freeList(stack);
  stack = NULL;

  return 0;
}

the expected output is

empty list: 
filled list: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 
list length = 23
filled stack: 17 0 6 12 18 1 7 13 19 2 8 14 20 3 9 15 21 4 10 16 22 5 11 
stack size = 23
remove did not find -4
remove did not find 24
list after removes: 1 2 3 5 6 7 9 10 11 13 14 15 17 18 19 21 22 
list length = 17
pop: 17
pop: 0
pop: 6
pop: 12
pop: 18
stack after pops: 1 7 13 19 2 8 14 20 3 9 15 21 4 10 16 22 5 11 
stack size = 18
list after reverse: 22 21 19 18 17 15 14 13 11 10 9 7 6 5 3 2 1 
  • What is the output? – pat Nov 12 '16 at 23:32
  • Put that into the question with better formatting, please! – pat Nov 12 '16 at 23:36
  • @pat i changed it, my apologies – Jacob Collins Nov 12 '16 at 23:40
  • What does the debugger tell you when you step through the code? – Ken White Nov 12 '16 at 23:41
  • Why do you keep saying expected output? What is the actual output? It will tell us where the program is seg faulting if we get the actual output – pat Nov 12 '16 at 23:44
  • Sorry I'm new to this my apologies on the misunderstanding. It will compile just fine, but when I try to run ./listtest i get an output that says segmentation fault (core dumped) @pat – Jacob Collins Nov 12 '16 at 23:47
  • The recurring error I get from the debugger is that i'm having multiple definitions of all my functions in listtest @KenWhite – Jacob Collins Nov 12 '16 at 23:51
  • The debugger doesn't say you have multiple definitions. The compiler would tell you that, and you wouldn't be able to compile and execute your app. Once again, what does the **debugger** tell you when you step through the code? – Ken White Nov 12 '16 at 23:53
  • @KenWhite so i have to compile it in this way gcc -o listtest linkedlist.c listtest.c When i do this it compiles, when i use the -g flag that is when I get the whole section of code I have no idea what it is saying. I'm trying to turn on the debugger but I can't get that far. If it helps the errors coming from listtest say something about an invalid symbol index – Jacob Collins Nov 13 '16 at 00:10
  • can you attach the definition of the struct ListNode and its members ? – shakram02 Nov 13 '16 at 00:17
  • The segfault comes from trying to execute ./listtest. And it will only compile if I leave out the -g flag – Jacob Collins Nov 13 '16 at 00:18

1 Answers1

1

Your segfault is happening in the pushStack() function. The line *head = *tempPush makes no sense here. When you pass in a NULL pointer for head, this attempts to dereference it, leading to the segfault. You can remove this line, and remove the unnecessary variable dataPush. Also, there is no reason to cast the result of malloc(), and it is better to use the pointer that you are assigning to as the argument for sizeof(). If the type is later changed, avoiding using an explicit type in sizeof() means fewer thing to remember to update. That means that the new pushStack() function is:

struct ListNode * pushStack(struct ListNode *head, int data)
{
    struct ListNode *tempPush = malloc(sizeof(*tempPush));
    tempPush->data = data;
    tempPush->next = head;

    return tempPush;
}

Your insertSorted() function contains an error. I am not exactly sure where this is; your function is more complicated that it needs to be, so I just wrote a new one for you. Similarly, your printList() function can be streamlined. I also modified the printList() function to match the expected output example that you provided:

struct ListNode * insertSorted(struct ListNode *head, int inputData)
{
    struct ListNode *prev = NULL;
    struct ListNode *curr = head;
    struct ListNode *new_node = createNode(inputData);

    while (curr) {
        if (inputData < curr->data) {
            new_node->next = curr;
            if (prev)
                prev->next = new_node;
            return (prev ? head : new_node);
        }
        prev = curr;
        curr = curr->next;
    }
    if (head) {
        new_node->next = NULL;
        prev->next = new_node;
    } else {
        head = new_node;
    }

    return head;
}

void printList(struct ListNode *head)
{
    struct ListNode *curr = head;

    while (curr) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    putchar('\n');
}

With these changes, the output is starting to match your expectations. There is a problem in your listLength() function, and there is a problem in your popStack() function. There may be further problems as well. I will let you wrestle with these issues; my suggestions should get you started. If you continue to have problems, send me a comment and I will try to help further.

Community
  • 1
  • 1
ad absurdum
  • 19,498
  • 5
  • 37
  • 60