1

I was trying to make a linked list using «Object Oriented» C. But I do not know how to backtrace segmentation fault, so I cannot find the solution.

Libraries, you know...

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

Within the structure I have two pointers to functions. These pointers mimic methods (something like that).

struct nodeList {
  int data;
  struct nodeList * nextPtr;
  void (*print)(struct nodeList *);
  void (*insert)(struct nodeList **, int);
  int (*delete)(struct nodeList **, int);
};

You know, I hate write struct every time.

typedef struct nodeList NodeList;
typedef NodeList * NodeListPtr;

Prototypes declarations. init is something like a constructor. I do not need a destructor, the function free() handles that.

NodeListPtr init(int);
void print(NodeListPtr);
void insert(NodeListPtr *, int);
int delete(NodeListPtr *, int);

int main(void)
{
  NodeListPtr myList = init(0);

  myList->insert(&myList, 5);

Here is where the segmentation fault happens :(

  myList->insert(&myList, 3);

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  myList->print(myList);

  free(myList);
  return 0;
}

Function declarations, you know. init is, like I said, something like a constructor. It returns an instance of NodeListPtr with the pointer funcions pointing to the rest of the functions.

NodeListPtr init(int data)
{
  NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeListPtr));
  instance->data = data;
  instance->nextPtr = NULL;
  instance->print = &print;
  instance->insert = &insert;
  instance->delete = &delete;

  return instance;
}

Iterates over the list and prints all data.

void print(NodeListPtr listPtr)
{
  NodeListPtr currentPtr = listPtr;

  while(currentPtr != NULL) {
    printf("%d -> ", currentPtr->data);
    currentPtr = currentPtr->nextPtr;
  }

  puts("(NULL)");
}

Inserts an element in an orderly manner.

void insert(NodeListPtr *selfPtr, int value)
{
  NodeListPtr newPtr;
  NodeListPtr previousPtr;
  NodeListPtr currentPtr;

  newPtr = init(value);

  if(newPtr != NULL) {
    previousPtr = NULL;
    currentPtr = *selfPtr;

    while(currentPtr != NULL && value > currentPtr->data) {
      previousPtr = currentPtr;
      currentPtr = currentPtr->nextPtr;
    }

    if(previousPtr == NULL) {
      newPtr->nextPtr = *selfPtr;
      *selfPtr = newPtr;
    } else {
      previousPtr->nextPtr = newPtr;
      newPtr->nextPtr = currentPtr;
    }
  } else {
    printf("Could not add %d. No memory available\n", value);
  }
}

Deletes an element of the list. If it does not exist, return null character.

int delete(NodeListPtr *selfPtr, int data)
{
  NodeListPtr tempPtr;
  NodeListPtr currentPtr;
  NodeListPtr previousPtr;

  if((*selfPtr)->data == data) {
    tempPtr = *selfPtr;
    *selfPtr = (*selfPtr)->nextPtr;
    free(tempPtr);

    return data;
  } else {
    previousPtr = *selfPtr;
    currentPtr = (*selfPtr)->nextPtr;

    while(currentPtr != NULL && currentPtr->data != data) {
      previousPtr = currentPtr;
      currentPtr = currentPtr->nextPtr;
    }

    if(currentPtr != NULL) {
      tempPtr = currentPtr;
      previousPtr->nextPtr = currentPtr->nextPtr;
      free(tempPtr);

      return data;
    }
  }

  return '\0';
}

And that's it. Like I said, I do not know how to do backtrace over segmentation fault with GDB, so I do not know how to fix it.

3
  • 1
    You can run your program on gdb and then ask to see the stack trace when it crashes. ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_42.html Commented Mar 22, 2015 at 10:15
  • when you force C to be something that its not , it tends to backfire at you.. Commented Mar 22, 2015 at 10:17
  • 7
    0) NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeListPtr)); --> NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeList)); Commented Mar 22, 2015 at 10:17

2 Answers 2

2

Replace

NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeListPtr));

with

NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeList));

in your code

– BLUEPIXY

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

Comments

0

Since your segmentation fault happens inside the insert function we can assume that one is to blame.

Problem seems to be in this code (didn't actually build the code... but by C rules the compiler is allowed to evaluate an expression in any order)

while(currentPtr != NULL && currentPtr->data != data) {
  previousPtr = currentPtr;
  currentPtr = currentPtr->nextPtr;
}

you code should instead be written as

while(currentPtr != NULL) {
    if(currentPtr->data != data) {
        previousPtr = currentPtr;
        currentPtr = currentPtr->nextPtr;
    } else {
        break;
    }
}

assuming that was your intent, didn't check the logic behind it actually, but the thing is otherwise you are dereferencing a null pointer there because although you do the check in order the compiler is free to evaluate it in any order it chooses to... so breaking it into a while and an if makes it so that your code is safe from dereferencing a null pointer.

1 Comment

Are you sure? I thought that the short circuit evaluation meant that it had to evaluate the left side first so that it wouldn't evaluate the right side if the left side was sufficient. en.wikipedia.org/wiki/Short-circuit_evaluation

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.