c ++删除指针问题,仍然可以访问数据

时间:2011-10-19 20:09:41

标签: c++ pointers

我真的不明白为什么这些指针可以访问...任何帮助赞赏

#include <iostream>

class Wicked{
public:
    Wicked() {};
    virtual ~Wicked() {};

    int a;
    int b;
};


class Test
{
public:
    Test() {};
    virtual ~Test() {};

    int c;

    Wicked * TestFunc()
    {
        Wicked * z;
        c = 9;
        z = new Wicked;
        z->a = 1;
        z->b = 5;
        return z;
    };
};

int main()
{
    Wicked *z;

    Test *t = new Test();
    z = t->TestFunc();

    delete z;
    delete t;

    // why can I set 'z' when pointer is already destroyed?
    z->a = 10;

    // why does z->a print 10?
    std::cout << z->a << std::endl;

    // why does t->c exist and print correct value?
    std::cout << t->c << std::endl;

    //------------------------------------------------------

    int * p = new int;
    *p = 4;

    // this prints '4' as expected
    std::cout << *p << std::endl;

    delete p;

    // this prints memory address as expected
    std::cout << *p << std::endl;

    return 0;
}

6 个答案:

答案 0 :(得分:10)

那是undefined behaviour。什么都有可能发生。这次你很幸运。或者也许是运气不好,因为最好得到运行时错误!下一次可能会遇到运行时错误。

理解为什么你会看到未定义行为的特定表现并不是非常有用。最好坚持你可以推理的明确定义的行为。

答案 1 :(得分:10)

删除指针不会将任何内存清零,因为这样做会占用CPU周期,而这不是C ++的内容。你有什么悬挂指针,可能是一个微妙的错误。像这样的代码有时可能会工作多年,只会在将来某个时候崩溃,因为程序中的其他地方会发生一些小的改动。

这是一个很好的理由,为什么当你删除它们指向的内存时你应该使用NULL指针,这样你就会在尝试取消引用指针时立即得到错误。清除使用像memset()这样的函数指向的内存有时也是个好主意。如果指向的内存包含一些您不希望其他(可能是面向用户的)程序部分访问的机密信息(例如明文密码),则尤其如此。

答案 2 :(得分:5)

C ++不会阻止你写入内存中的任意位置。当您使用newmalloc分配内存时,C ++会在内存中找到一些未使用的空间,将其标记为已分配(以便不会意外地再次分发),并为您提供其地址。 / p>

然而,一旦你delete那个内存,C ++就会将其标记为免费,并且可以将其发送给任何要求它的人。您仍然可以写入并从中读取,但此时,其他人可能正在使用它。当您在内存中写入该位置时,您可能会覆盖您在其他位置分配的某些值。

答案 3 :(得分:4)

下面

// why can I set 'z' when pointer is already destroyed?
z->a = 10;

z仍指向记忆位置 但它不再对你好。你已经将它传递给删除并表示要处理这个指针。它的作用不再是你的担忧。就像你卖车一样;它仍然存在,但它不是你的,所以打开门并查看可能是可能的,但它可能导致警察逮捕你。

与删除的指针相同,内存存在,但不属于你。
如果您查看它可能会起作用,但它也可能导致分段错误,因为库已刷新页面(您永远不知道)。

答案 4 :(得分:3)

delete z;只是释放指向的内存z,它不会破坏指针本身。

因此z成为wild pointer

答案 5 :(得分:2)

因为删除内存块并不会将指向它的所有指针的值归零。删除内存只是说明内存可用于某些其他目的。在此之前,内存可能看起来完好无损 - 但是你不能指望它,并且在一些编译器/运行时/体系结构组合中,你的程序会表现得不同 - 它甚至可能会崩溃。