我有这个结构
typedef struct node
{
struct node *prev;
void *data;
struct node *next;
}NODE;
typedef struct head
{
unsigned int length;
struct node *first;
struct node *last;
}HEAD;
STATUS addNode(HEAD *head, NODE *newNode, int loc)
{
int i;
STATUS ret = SUCCESS;
NODE *curPtr;
if(head && newNode && loc && (loc <= (head->length)+1))
{
if(loc == 1)
{
newNode->prev = NULL;
newNode->next = head->first;
if(head->first)
head->first = newNode;
}
else
{
curPtr = head->first;
for(i=1; i<(loc-1); i++){
curPtr = curPtr->next;
}
newNode->prev = curPtr;
newNode->next = curPtr->next;
if(curPtr->next){
curPtr->next->prev = newNode;
}
curPtr->next = newNode;
}
head->length++;
}
else
ret = FAILURE;
return ret;
}
STATUS removeNode(HEAD *head,NODE *nodeToRemove)
{
STATUS ret = SUCCESS;
NODE *curPtr;
if(head && head->first)
{
curPtr = nodeToRemove->prev;
curPtr->next = nodeToRemove->next;
if(!(curPtr->next)){
curPtr->next = head->first;
}
head->length--;
}
else
ret = FAILURE;
return ret;
}
我知道我没有从列表中删除免费(节点),此调用是在其他地方进行的
我的问题是,有时在添加节点的newNode->next = curPtr->next;
行上它会出现分段错误
答案 0 :(得分:1)
好的,让我们从我的第一条评论开始:当您使用addNode
调用loc == 1
函数时会发生什么:初始化新节点,因此它的next
指针指向列表的旧头部,prev
指针指向NULL
。这一切都很好,但随后你的问题开始了。如果列表不为空,则只将新节点添加到列表。您也不会更改以前的头节点prev
指针。
这意味着如果列表为空(即head->first
为NULL
时),则不会添加节点,列表将继续为空。如果列表不为空,那么你有一个双链表,你只能走一条路(从(新的)第一个节点到(新的)第二个节点,你不能走相反的方向,因为你没有设置这样的链接。
现在我的第二和第三条评论:loc != 1
时的循环。首先,如果loc == 0
,它将不会运行,这意味着它将添加到头部(这是您在loc == 1
时尝试执行的操作)。如果列表为空,这将无效,因为curPtr
将为NULL
,当您取消引用该指针时,您将拥有undefined behavior。
其次,假设您已设法将一些节点添加到列表中,并且您传递的值大于节点数加上列表中的一个loc
(即如果您有一个节点,那么您传递一个大于2
的值,或者你有五个节点并传递一个大于6
的值),然后循环将迭代一次到多次,让curPtr
为{{1} }}。您不会在任何地方检查,这意味着您迟早(在循环中或之后)尝试取消引用导致undefined behavior的NULL
指针。
Undefined behavior是崩溃的最常见原因,例如您拥有的崩溃。下次发生崩溃时,首先应该使用调试器并在其中运行程序。调试器将在崩溃位置停止,让您检查函数调用堆栈,以及向上调用堆栈。您还可以检查调用堆栈每个级别的变量值(如果调试器具有该级别的信息)。您还应该尝试在调试器中逐行遍历代码,针对不同的场景,看看您打算实际发生的事情如果您仍然难倒,那么您可以来SO并发布一个关于它的问题。在编译器旁边,调试器是程序员的最佳工具。哦,广告说编译器,总是在尽可能多的警告启用的情况下构建,因为编译器非常擅长检测可疑的东西并且可能导致UB(未定义的行为)。
答案 1 :(得分:0)
可能curptr->next
未分配给任何不一定使其指向NULL的内容,因此您可能会在运行时遇到分段错误。确保在构建列表时,NODE中的所有指针在对它们进行任何赋值/操作之前都会初始化为NULL。
请参阅:C: Why do unassigned pointers point to unpredictable memory and NOT point to NULL?