尝试将节点添加到链表前面时出现段错误
Segfault when trying to add a node to front of linked list
我很困惑为什么我会在这段代码中遇到段错误。 gdb 说当我尝试将数据分配给列表-> 值时会发生段错误,但我无法弄清楚为什么会这样。感谢您的帮助!
int main(){
SingleLinkedListNode *list = 0;
int element = 10;
pushFront(list, element);
//cout << list->value << endl;
}
SingleLinkedListNode *head = NULL;
void pushFront(SingleLinkedListNode*& list, const int data){
//checks if head points to null. if it does,
//make head point to list and the data assigns to list->value
if(list == NULL){
head = list;
list->value = data; //gdb says segfault occurs here
return;
}
// if head != null then make list point to the node head points to, assign
// value to list->value and last make the head point to list node
list->next = head;
head = list;
list->value = data;
}
我认为这是出于某种学术目的,因为实际上,当您可以只使用 std::forward_list
并完成它时,没有任何头脑正常的人会重新发明一个链表(不要重新发明轮子)。
您似乎对尝试将全局 head
指针绑定到 (a) 不需要它和 (b) 不需要它的解决方案感到困惑。更糟糕的是,您似乎不明白链表数据结构是 节点 的链,而且这些节点并非凭空而来。
你的错误来自这里:
if(list == NULL){ // test that list is NULL
head = list;
list->value = data; // list is NULL, so this dereference is bad.
return;
有几处错误,最麻烦的是试图在 none 应该存在的地方修饰一个全局 head
指针。此外,在链表上挂一个新节点需要.... 一个新节点(我知道;这是一个疯狂的世界)。
假设您的结构如下所示:
struct SingleLinkedListNode
{
int data;
SingleLinkedListNode *next;
SingleLinkedListNode(int arg=0, SingleLinkedListNode *nxt = nullptr)
: data(arg)
, next(nxt)
{
}
// squelch these
SingleLinkedListNode(const SingleLinkedListNode&) = delete;
SingleLinkedListNode& operator =(const SingleLinkedListNode&) = delete;
};
将项目推到passed-in列表前面的方法很简单:
void pushFront(SingleLinkedListNode*& lst, int data)
{
lst = new SingleLinkedListNode(data, lst);
}
请注意,这会执行以下操作:
- 将新节点的数据值作为第一个参数传递给
SingleLinkedListNode
构造函数。
- 将现有列表头指针值作为第二个参数传递给
SingleLinkedListNode
构造函数。这将用作正在构建的新节点的 next
成员值,从而将新节点链接到当前列表头。
- 最后,将结果 pointer-to-node 存储为新的链表头,它将传播回调用者,因为
lst
是对 caller-provided 的 non-const 引用指针。
这也意味着您不需要(也不应该想要)全局 head
。下面提供了此解决方案的完整示例。
#include <iostream>
struct SingleLinkedListNode
{
int data;
SingleLinkedListNode *next;
SingleLinkedListNode(int arg=0, SingleLinkedListNode *nxt = nullptr)
: data(arg)
, next(nxt)
{
}
// squelch these (Rule of 3/5/0 habit)
SingleLinkedListNode(const SingleLinkedListNode&) = delete;
SingleLinkedListNode& operator =(const SingleLinkedListNode&) = delete;
};
void pushFront(SingleLinkedListNode*& lst, int data)
{
lst = new SingleLinkedListNode(data, lst);
}
void printList(const SingleLinkedListNode *lst)
{
if (lst)
{
std::cout << lst->data;
lst = lst->next;
while (lst)
{
std::cout << ',' << lst->data;
lst = lst->next;
}
std::cout << '\n';
}
}
void freeList(SingleLinkedListNode*& lst)
{
while (lst)
{
SingleLinkedListNode *tmp = lst;
lst = lst->next;
delete tmp;
}
}
int main()
{
SingleLinkedListNode *head = nullptr;
for (int i=1; i<=10; ++i)
pushFront(head, i);
printList(head);
freeList(head);
}
输出
10,9,8,7,6,5,4,3,2,1
我很困惑为什么我会在这段代码中遇到段错误。 gdb 说当我尝试将数据分配给列表-> 值时会发生段错误,但我无法弄清楚为什么会这样。感谢您的帮助!
int main(){
SingleLinkedListNode *list = 0;
int element = 10;
pushFront(list, element);
//cout << list->value << endl;
}
SingleLinkedListNode *head = NULL;
void pushFront(SingleLinkedListNode*& list, const int data){
//checks if head points to null. if it does,
//make head point to list and the data assigns to list->value
if(list == NULL){
head = list;
list->value = data; //gdb says segfault occurs here
return;
}
// if head != null then make list point to the node head points to, assign
// value to list->value and last make the head point to list node
list->next = head;
head = list;
list->value = data;
}
我认为这是出于某种学术目的,因为实际上,当您可以只使用 std::forward_list
并完成它时,没有任何头脑正常的人会重新发明一个链表(不要重新发明轮子)。
您似乎对尝试将全局 head
指针绑定到 (a) 不需要它和 (b) 不需要它的解决方案感到困惑。更糟糕的是,您似乎不明白链表数据结构是 节点 的链,而且这些节点并非凭空而来。
你的错误来自这里:
if(list == NULL){ // test that list is NULL
head = list;
list->value = data; // list is NULL, so this dereference is bad.
return;
有几处错误,最麻烦的是试图在 none 应该存在的地方修饰一个全局 head
指针。此外,在链表上挂一个新节点需要.... 一个新节点(我知道;这是一个疯狂的世界)。
假设您的结构如下所示:
struct SingleLinkedListNode
{
int data;
SingleLinkedListNode *next;
SingleLinkedListNode(int arg=0, SingleLinkedListNode *nxt = nullptr)
: data(arg)
, next(nxt)
{
}
// squelch these
SingleLinkedListNode(const SingleLinkedListNode&) = delete;
SingleLinkedListNode& operator =(const SingleLinkedListNode&) = delete;
};
将项目推到passed-in列表前面的方法很简单:
void pushFront(SingleLinkedListNode*& lst, int data)
{
lst = new SingleLinkedListNode(data, lst);
}
请注意,这会执行以下操作:
- 将新节点的数据值作为第一个参数传递给
SingleLinkedListNode
构造函数。 - 将现有列表头指针值作为第二个参数传递给
SingleLinkedListNode
构造函数。这将用作正在构建的新节点的next
成员值,从而将新节点链接到当前列表头。 - 最后,将结果 pointer-to-node 存储为新的链表头,它将传播回调用者,因为
lst
是对 caller-provided 的 non-const 引用指针。
这也意味着您不需要(也不应该想要)全局 head
。下面提供了此解决方案的完整示例。
#include <iostream>
struct SingleLinkedListNode
{
int data;
SingleLinkedListNode *next;
SingleLinkedListNode(int arg=0, SingleLinkedListNode *nxt = nullptr)
: data(arg)
, next(nxt)
{
}
// squelch these (Rule of 3/5/0 habit)
SingleLinkedListNode(const SingleLinkedListNode&) = delete;
SingleLinkedListNode& operator =(const SingleLinkedListNode&) = delete;
};
void pushFront(SingleLinkedListNode*& lst, int data)
{
lst = new SingleLinkedListNode(data, lst);
}
void printList(const SingleLinkedListNode *lst)
{
if (lst)
{
std::cout << lst->data;
lst = lst->next;
while (lst)
{
std::cout << ',' << lst->data;
lst = lst->next;
}
std::cout << '\n';
}
}
void freeList(SingleLinkedListNode*& lst)
{
while (lst)
{
SingleLinkedListNode *tmp = lst;
lst = lst->next;
delete tmp;
}
}
int main()
{
SingleLinkedListNode *head = nullptr;
for (int i=1; i<=10; ++i)
pushFront(head, i);
printList(head);
freeList(head);
}
输出
10,9,8,7,6,5,4,3,2,1