提问人:M1001 提问时间:11/11/2023 最后编辑:M1001 更新时间:11/11/2023 访问量:85
分段错误错误单向链表 C++ [已关闭]
Segmentation fault error singly linked lists C++ [closed]
问:
为什么会出现错误:
int main(){
lista *head, *x;
head = nullptr;
const int len = 3;
int y[len] = {13, 4, 32};
for(int i = len - 1; i >= 0; i--){
x = new lista;
x -> val = y[i];
x -> next = head;
head = x;
}
lista *p = head;
// Changing lines are the next ones
while(p->next != nullptr){
p = p->next;
}
delete p;
p = nullptr;
print_lista(head);
return 0;
}
但事实并非如此:
int main(){
lista *head, *x;
head = nullptr;
const int len = 3;
int y[len] = {13, 4, 32};
for(int i = len - 1; i >= 0; i--){
x = new lista;
x -> val = y[i];
x -> next = head;
head = x;
}
lista *p = head;
// Changing lines are the next ones
while(p->next->next != nullptr){
p = p->next;
}
delete p->next ;
p->next = nullptr;
print_lista(head);
return 0;
}
它也不能以这种方式工作
while(p->next != nullptr){
p = p->next;
}
p = p->next;
delete p;
p = nullptr;
这是给定的错误:
受监控的命令转储核心
分段故障
这不是一回事吗?在第一种情况下,p 是倒数第二个元素的下一个值,在第二种情况下,p 是倒数第三个元素的下一个值,因此 p->next 应该是倒数第二个元素的下一个值。 结构如下:
struct lista{
int val;
lista *next;
};
错误发生在“delete...;”行中
本·沃伊特(Ben Voigt)的编辑
为什么?如果我运行这样的测试:
lista *p = head;
while (p->next->next != nullptr){
p = p->next;
}
cout << p->next;
lista *z = head;
while (z->next != nullptr){
z = z->next;
}
cout << endl << z;
p 和 z 都是0x5575909e3eb0的,它们不是一样吗?
答:
4赞
Ben Voigt
11/11/2023
#1
问题在于,在失败的代码中,您正在解除分配列表中的最后一项,而不会将其从列表中删除。结果是一个包含悬空指针的列表,因此遍历该列表的后续操作具有未定义的行为。
工作代码确实将其从列表中分离出来。
为了回答你的思想实验,让我们让它变得更简单。
std::cout << head << '\n';
lista* z = head;
std::cout << z << '\n';
z = nullptr;
// now how many items are in the list?
std::cout << head << '\n';
std::cout << z << '\n';
// are `head` and `z` really equivalent?
z = head;
head = nullptr;
// now how many items are in the list?
std::cout << head << '\n';
std::cout << z << '\n';
评论
0赞
M1001
11/11/2023
为什么?如果我运行这样的测试:lista *p = head;while (p->next->next != NULL){ p = p->next ;} cout << p->next;lista *z = 头部;while (z->next != NULL){ z = z->next ;} cout << endl << z;p 和 z 都是0x5575909e3eb0的,它们不是一样吗?
0赞
M1001
11/11/2023
这在评论中是不可缩进的,我编辑了问题
1赞
Ben Voigt
11/11/2023
和 都是指向列表中项的指针的副本。 实际上是列表的一部分。 将该对象从列表中分离。 在不更改列表的情况下擦除副本。p
z
p->next
p->next = nullptr;
z = nullptr;
0赞
M1001
11/11/2023
非常感谢,我现在明白了,我表现得好像 p 和 head 是一样的,而不仅仅是指向同一件事,但现在另一个问题出现在我面前,如果它只是删除一个副本,为什么它会抛出致命错误?它应该不起作用
1赞
Ben Voigt
11/11/2023
p
是指向列表中的真实节点,所以 ,解除分配事物指向的(即 ),解除分配的是真实项目而不是副本。 不作用于指针变量。delete p;
p
*p
delete
p
评论
nullptr
NULL
p
delete p
std::forward_list