为什么会出现错误:
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;
};
错误发生在“删除...;”线
为本·沃伊特编辑
为什么?如果我运行这样的测试:
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,不是一样吗?
问题在于,在失败的代码中,您正在释放列表中的最后一项,而不是将其从列表中删除。结果是一个包含悬空指针的列表,因此稍后遍历列表的操作具有未定义的行为。
工作代码确实将其从列表中分离出来。
为了回答你的思想实验,让我们让它变得更简单。
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';