我真的不明白为什么这些指针可以访问...任何帮助赞赏
#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;
}
答案 0 :(得分:10)
那是undefined behaviour。什么都有可能发生。这次你很幸运。或者也许是运气不好,因为最好得到运行时错误!下一次可能会遇到运行时错误。
理解为什么你会看到未定义行为的特定表现并不是非常有用。最好坚持你可以推理的明确定义的行为。
答案 1 :(得分:10)
删除指针不会将任何内存清零,因为这样做会占用CPU周期,而这不是C ++的内容。你有什么悬挂指针,可能是一个微妙的错误。像这样的代码有时可能会工作多年,只会在将来某个时候崩溃,因为程序中的其他地方会发生一些小的改动。
这是一个很好的理由,为什么当你删除它们指向的内存时你应该使用NULL指针,这样你就会在尝试取消引用指针时立即得到错误。清除使用像memset()这样的函数指向的内存有时也是个好主意。如果指向的内存包含一些您不希望其他(可能是面向用户的)程序部分访问的机密信息(例如明文密码),则尤其如此。
答案 2 :(得分:5)
C ++不会阻止你写入内存中的任意位置。当您使用new
或malloc
分配内存时,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)
因为删除内存块并不会将指向它的所有指针的值归零。删除内存只是说明内存可用于某些其他目的。在此之前,内存可能看起来完好无损 - 但是你不能指望它,并且在一些编译器/运行时/体系结构组合中,你的程序会表现得不同 - 它甚至可能会崩溃。