c++删除指针问题,仍然可以访问数据
我真的不明白为什么这些指针可以访问......任何帮助表示赞赏
#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;
}
I don't really understand why are those pointer accessible ... any help appreciated
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
删除指针不会将任何内存归零,因为这样做会占用 CPU 周期,而这不是 C++ 的目的。你所拥有的是一个悬空指针,并且可能存在一个微妙的错误。这样的代码有时可以工作数年,但在将来的某个时刻,当程序中的其他地方进行了一些微小的更改时,就会崩溃。
这是为什么当您删除指针指向的内存时应该将指针置为 NULL 的一个很好的理由,这样,如果您尝试取消引用该指针,您将立即收到错误。有时使用 memset() 等函数清除指向的内存也是一个好主意。如果指向的内存包含您不希望程序的其他部分(可能是面向用户的部分)访问的机密内容(例如明文密码),则尤其如此。
Deleting a pointer doesn't zero out any memory because to do so would take CPU cycles and that's not what C++ is about. What you have there is a dangling pointer, and potentially a subtle error. Code like this can sometimes work for years only to crash at some point in the future when some minor change is made somewhere else in the program.
This is a good reason why you should NULL out pointers when you've deleted the memory they point to, that way you'll get an immediate error if you try to dereference the pointer. It's also sometimes a good idea to clear the memory pointed to using a function like memset(). This is particularly true if the memory pointed to contains something confidential (e.g. a plaintext password) which you don't want other, possibly user facing, parts of your program from having access to.
这是未定义的行为。任何事情都有可能发生。这次你很幸运。或者可能不太幸运,因为最好得到运行时错误!下一次你可能会遇到运行时错误。
推理为什么会看到未定义行为的特定表现并不是很有用。最好坚持您可以推理的明确定义的行为。
That's undefined behaviour. Anything can happen.You were lucky this time. Or perhaps unlucky since it would be preferable to get a runtime error! Next time round maybe you'll get a runtime error.
It's not really very useful to reason about why you see a particular manifestation of undefined behaviour. It's best to stick to the well-defined behaviour about which you can reason.
C++ 不会阻止您写入内存中的任意位置。当您使用 new 或 malloc 分配内存时,C++ 会在内存中找到一些未使用的空间,将其标记为已分配(这样就不会意外地再次分配),并且给你它的地址。
然而,一旦您
删除
该内存,C++ 会将其标记为空闲,并可能将其分发给任何需要它的人。您仍然可以对其进行写入和读取,但此时其他人可能正在使用它。当您写入内存中的该位置时,您可能会覆盖在其他地方分配的一些值。C++ won't stop you from writing to an arbitrary location in memory. When you allocate memory with
new
ormalloc
, C++ finds some unused space in memory, marks it as allocated (so that it doesn't accidentally get handed out again), and gives you its address.Once you
delete
that memory however, C++ marks it as free and may hand it out to anyone that asks for it. You can still write to it and read from it, but at this point, someone else might be using it. When you write to that place in memory, you may be overwriting some value you have allocated elsewhere.这里
z 仍然指向内存位置。
但它不再属于你了。您已将其传递给删除并表示要处理该指针。它做什么不再是你关心的事。就像你卖掉你的车一样;它仍然存在,但不是你的,因此打开门并查看可能是可能的,但这可能会导致警察逮捕你。
与删除的指针相同,内存存在但不属于您。
如果您查看内部,它可能会起作用,但也可能会导致分段错误,因为库已刷新页面(您永远不知道)。
Here
z still points at a memory location.
But it no longer blongs to you. You have passed it to delete and said take care of this pointer. What it does is no longer your concern. Its like when you sell your car; it still exists but its not yours so opening the door and looking in may be possible, but it may result in the police arresting you.
Same with deleted pointers the memory exists but does not belong to you.
If you look inside it may work, but it may also cause a segmentation fault as the library has flushed the page (you never know).
delete z;
只是释放z
指向的内存,它不会破坏指针本身。因此,
z
成为野指针。delete z;
just deallocates the memoryz
was pointing to, it does not destroy the pointer itself.So
z
becomes a wild pointer.因为删除一块内存并不会将所有指向它的指针的值清零。删除内存只是表明该内存可用于其他目的。在此之前,内存可能看起来完好无损 - 但你不能指望它,并且在某些编译器/运行时/体系结构组合上,你的程序将表现不同 - 它甚至可能崩溃。
Because deleting a block of memory does not zero the value of all pointers that point to it. Deleting memory merely makes a note that the memory is available to be allocated for some other purpose. Until that happens, the memory may appear to be intact -- but you can't count on it, and on some compiler/runtime/architecture combinations, your program will behave differently -- it may even crash.