分段错误 - 面向对象 C - 链表
Segmentation Fault - Object Oriented C - Linked List
我正在尝试使用 «Object Oriented» 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 就像我说的,类似于构造函数。它 return 是 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);
}
}
删除列表的一个元素。如果不存在,return空字符。
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 '[=19=]';
}
就是这样。就像我说的,我不知道如何使用 GDB 对分段错误进行回溯,所以我不知道如何修复它。
替换
NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeListPtr));
和
NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeList));
在您的代码中
– 蓝精灵
由于您的分段错误发生在插入函数内部,我们可以假设一个是罪魁祸首。
问题似乎出在这段代码中(实际上并未构建代码...但根据 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 使它成为安全的,这样您的代码就可以安全地取消引用空指针。
我正在尝试使用 «Object Oriented» 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 就像我说的,类似于构造函数。它 return 是 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);
}
}
删除列表的一个元素。如果不存在,return空字符。
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 '[=19=]';
}
就是这样。就像我说的,我不知道如何使用 GDB 对分段错误进行回溯,所以我不知道如何修复它。
替换
NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeListPtr));
和
NodeListPtr instance = (NodeListPtr) malloc(sizeof(NodeList));
在您的代码中
– 蓝精灵
由于您的分段错误发生在插入函数内部,我们可以假设一个是罪魁祸首。
问题似乎出在这段代码中(实际上并未构建代码...但根据 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 使它成为安全的,这样您的代码就可以安全地取消引用空指针。