涉及删除操作的C ++指针问题

时间:2019-02-11 00:31:46

标签: c++

这是个问题,我应该弄清楚错误是什么。

#include <cstdio>

struct Node {
    int data;
    Node* next;
};

void foo(Node* n) {
    delete n->next;
}

Node* create(int x, Node* n) {
    Node* n1 = new Node();
    n1->data = x;
    n1->next = n;

    return n1;
}

int main(void) {
    Node* n1 = create(1, NULL);
    Node* n2 = create(2, n1);

    foo(n2);
    Node* n3 = create(3, NULL);

    n1->data = 42;

    printf("%d\n", n3->data);
    delete n2;
    delete n3;

    return 0;
}

问题是,代码将打印数字42,而不是预期的3。 我通过使用调试器将其范围缩小到以下问题: 在create方法内部调用行Node* n3 = create(3, NULL)时,第一行创建的n1实际上与首先创建然后删除的n1相同。这与创建n2时发生的情况相反,后者在create函数中的n1实际上有一个新地址。 因此,出于某种原因,似乎在foo中执行删除操作之后,new Node()操作不再返回新地址。

仅供参考,当交换foo(n2)Node* n3 = create(3, NULL)行时,该代码将打印3,这是预期的行为。

谢谢

2 个答案:

答案 0 :(得分:3)

调用foo(n2)时,n1n2->next都指向同一个Node对象。先foo个对象,再delete个对象。此时,n1n2->next都指向无效的位置。这意味着,当您以后尝试分配给n1->data时,程序的行为将变得不确定。在这种特定情况下,n3指向的对象最终位于n1最初指向的对象所在的位置,而您最终通过n1更改了该对象。虽然不能保证。从无到有,程序崩溃都可能发生。

答案 1 :(得分:0)

您的写入无效。 foo(n2)有效地调用delete n1,然后分配另一个Node;在您的情况下,新分配的内存与n1具有相同的地址(自从释放内存以来,该地址现在可用)。

如果您在valgrind下运行程序,它将报告无效的写操作。