分段故障 - 面向对象的C - 链表

时间:2015-03-22 10:12:14

标签: c pointers data-structures linked-list singly-linked-list

我试图使用«面向对象»C创建一个链表。 但我不知道如何回溯分段故障,所以我 无法找到解决方案。

图书馆,你知道......

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

在结构中我有两个指向函数的指针。这些指针模仿方法(类似的东西)。

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

你知道,我讨厌每次都写 struct

typedef struct nodeList NodeList;
typedef NodeList * NodeListPtr;

原型声明。 init 类似于构造函数。我不需要析构函数,函数free()处理它。

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

这是分段故障发生的地方:(

  myList->insert(&myList, 3);

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

  myList->print(myList);

  free(myList);
  return 0;
}

函数声明,你知道。 像我说的那样, init 就像一个构造函数。它返回一个NodeListPtr实例,其指针功能指向其余的函数。

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

迭代列表并打印所有数据。

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

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

  puts("(NULL)");
}

以有序的方式插入元素。

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

删除列表中的元素。如果它不存在,则返回空字符。

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';
}

就是这样。就像我说的,我不知道如何使用GDB对分段错误进行回溯,所以我不知道如何修复它。

2 个答案:

答案 0 :(得分:2)

替换

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

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

代码

- BLUEPIXY

答案 1 :(得分:0)

由于你的分段错误发生在插入函数中,我们可以认为应该责怪。

问题似乎出现在这段代码中(实际上没有构建代码......但是通过C规则,允许编译器以任何顺序计算表达式)

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

您应该将代码写为

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

假设这是你的意图,实际上没有检查它背后的逻辑,但事实是你在那里取消引用空指针,因为尽管你按顺序进行检查,编译器可以按任意顺序自由评估它选择......所以把它分解成一段时间,并且if使得你的代码可以安全地取消引用空指针。