我用 C 编写了一个非常基本的链表,只支持两个操作 - 在列表顶部插入一个节点并迭代列表以打印每个节点的值。我面临的问题是我在执行时遇到分段错误。这是我的代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct linkedList
{
int data;
struct linkedList *next;
};
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->next = malloc(sizeof(struct linkedList));
node->next = NULL;
node = NULL;
return node;
}
//insert a node at the top of the linked list
struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
{
if(top == NULL)//the element we insert is the 1st element for the linked list
{
node->next = NULL;
//the first element points to NULL since it has no successors
}
else//there is already an element in the list
{
node->next = top;
}
return node;
}
void iterate(struct linkedList* top)
{
while(top->next != NULL)
{
printf("Data = %dn", top->data);
top = top->next;
}
}
int main()
{
struct linkedList *a,*b,*c,*root;
a = createNode(2);
b = createNode(10);
c = createNode(23);
root = insertTop(NULL,a);//these 3 lines provoke a segmentation fault
root = insertTop(root,b);
root = insertTop(root,c);
iterate(root);//the result I expect here is 23,10,2
return 0;
}
我知道这个问题已经在stackoverflow上被问了很多次,但我仍然无法弄清楚为什么我的代码不能按预期工作。你能向我解释问题在哪里以及如何解决它吗?谢谢
有两个主要问题。 第一createNode
:
您为struct linkedList
分配空间并将其分配给node
,这很好。 但是你对node->next
做同样的事情. 所以你实际上是在创建两个节点,但随后你node->next
设置为 NULL,丢失对你分配的第二位内存的引用,从而产生内存泄漏。 当您对node
执行相同操作时,也会发生同样的情况。 最终结果是始终为新节点返回 NULL。 此外,您不会value
分配给任何内容。
只需执行第一次分配,将value
分配给data
,然后将next
初始化为 NULL:
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->data = value;
node->next = NULL;
return node;
}
下一期是iterate
:
while(top->next != NULL)
这会导致迭代在当前节点是最后一个节点时停止,因此您不会打印最后一个节点。 此外,由于最初实现createNode
的方式,root
指针为 NULL,因此最终会取消引用 NULL 指针,从而导致核心转储。
您想改为测试top
是否为 NULL:
while(top != NULL)
第三个问题是清理。 您需要定义一个函数来free
程序退出之前分配的内存。 你可以这样做:
void cleanup(struct linkedList *top)
{
struct linkedList *temp;
while (top != NULL) {
temp = top;
top = top->next;
free(temp);
}
}
这个:
node = NULL;
在createNode()
函数中看起来不太好。事实上,整个功能看起来并不那么好。它应该是这样的:
struct linkedList* createNode(int value)
{
struct linkedList *node = malloc(sizeof *node);
node->next = NULL;
node->data = value;
return node;
}
它真的不应该分配多个节点,这是不理智的。
如果你想创建一个节点,你只需要为一个节点分配mamory。像这样调整你的代码:
struct linkedList* createNode(int value)
{
struct linkedList *node = malloc(sizeof(struct linkedList));
node->next = NULL;
node->data = value;
return node;
}
除此之外,您必须更改函数中while
循环的终止条件iterate
:
void iterate( struct linkedList *top )
{
while( top != NULL) // if to is not NULL you can print its data
// ^^^
{
printf("Data = %dn", top->data);
top = top->next;
}
}
您可以简化您的功能insertTop
:
struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
{
if( node == NULL ) // test if node is not NULL
return top;
node->next = top; // successor of new node is top (top possibly is NULL)
return node;
}
不要忘记在main
末尾free
您的列表:
int main()
{
struct linkedList *root = NULL;
root = insertTop( root, createNode(2) );
root = insertTop( root, createNode(10) );
root = insertTop( root, createNode(23) );
iterate(root);
while ( root != NULL )
{
struct linkedList *temp = root;
root = root->next;
free( temp );
}
return 0;
}
除此之外,您还可以将createNode
和insertTop
组合到一个功能createTop
:
struct linkedList* createTop( struct linkedList* top, int value )
{
struct linkedList *node = malloc(sizeof(struct linkedList));
node->next = top;
node->data = value;
return node;
}
你那里有很多问题。
在函数createNode()
中,您将内存分配给node
,然后通过执行node = NULL
将其丢弃。
松开这些语句,因为它们会产生内存泄漏。
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->data = value;
node->next = NULL;
return node;
}