简体   繁体   English

删除指向对象的C ++指针

[英]Deleting C++ pointers to an object

I thought that the delete command would free up memory I allocated. 我以为删除命令会释放我分配的内存。 Can someone explain why it seems I still have the memory in use after delete? 有人可以解释为什么删除后我似乎仍在使用内存吗?

class Test
{
public:
    int time;
};

int main()
{
    Test *e;

    e = new Test;

    e->time = 1;
    cout << e->time << endl;

    delete e;

    e->time = 2;
    cout << e->time << endl;

    return(0);
}

I expected a seg-fault after e->time = 2; 我期望e-> time = 2后出现段故障;

Thanks! 谢谢!

I expected a seg-fault after e->time = 2; 我期望e-> time = 2后出现段故障;

You shouldn't "expect" anything to happen; 您不应该“期望”任何事情; you are invoking undefined behavior, which by definition is, well, undefined. 您正在调用未定义的行为,根据定义,这是未定义的。 That means that you can no longer make any reasonable expectations about the state of your program. 这意味着您不能再对程序的状态做出任何合理的期望。

Undefined behavior is just that, undefined. 未定义的行为就是未定义的行为。 It can even work if it so pleases. 如果可以的话,它甚至可以工作。

When you "delete" memory, you are basically returning the allocated memory back to the heap. 当“删除”内存时,基本上就是将分配的内存返回到堆中。 This just means that the data structure used to organize heap memory is updated to indicate that the memory is now available to use. 这仅表示用于组织堆内存的数据结构已更新,以指示该内存现在可供使用。 It is not cleared out or anything like that. 它没有清除或类似的东西。 You are accessing memory that still exists, but belongs to the operating system at this point. 您正在访问仍存在但属于操作系统的内存。 This is undefined behavior. 这是未定义的行为。

EDIT: 编辑:

And by the way, a seg fault occurs when you try to read memory from a segment that you do not have read permissions for. 顺便说一句,当您尝试从没有读取权限的段中读取内存时,就会发生段错误。 In a flat memory model this probably means you tried to read memory in kernel space; 在平面内存模型中,这可能意味着您试图读取内核空间中的内存。 probably because you dereferenced a bad pointer. 可能是因为您取消引用了错误的指针。

Accessing deleted object is an undefined behavior. 访问已删除的对象是未定义的行为。 Anything can happen 什么都可能发生

Dereferencing a pointer to an object that has been deleted is undefined. 取消引用指向已删除对象的指针是未定义的。 The memory for that object probably hasn't been overwritten yet so your object is still there (If it works at all). 该对象的内存可能尚未被覆盖,因此您的对象仍然存在(如果可以使用的话)。

Pointers are a container for an address in memory. 指针是内存中地址的容器。 You can always use a declared pointer, but unless it's initialized to memory that you own, expect confusion and worse. 您始终可以使用声明的指针,但是除非将其初始化为您拥有的内存,否则会造成混乱甚至更糟。

Test *e;
e->time = 2;

also compiles and won't work. 也可以编译,无法正常工作。 Minimize this type of confusion so: 尽量减少此类混乱,因此:

{
  boost::scoped_ptr<Test> e(new Test);

  e->time = 1;
  cout << e->time << endl;

  e->time = 2;
  cout << e->time << endl;
}

No new/delete needed, just enclosing braces to define the scope, and an appropriate smart pointer. 不需要new/delete ,只需将花括号括起来以定义范围,并使用适当的智能指针即可。

run it under valgrind. 在valgrind下运行它。 it will tell you that you did a bad thing 它会告诉你你做了一件坏事

As others have said, what you've done is wrong, but you can't expect any particular behavior. 正如其他人所说,您所做的是错误的,但是您不能指望任何特定的行为。

What's probably happening on most modern systems is the memory allocated for and occupied by e is on a memory page mapped as valid for your program, and the fact that you have delete d e , doesn't not undo that mapping. 在大多数现代系统上可能发生的情况是,为e分配和占用的内存在映射为对您的程序有效的内存页面上,并且您delete d e并不会撤消该映射。

So you are still accessing memory that your application has permission to use from OS. 因此,您仍在访问应用程序有权从OS使用的内存。 Thus, no segmentation fault. 因此,没有分割错误。 It is possible, however that if enough things happen between delete e and accessing that memory the page will have been remapped. 可能的,但是,如果有足够的东西之间发生delete e和访问内存页面将被重新映射。 Then you get a seg fault. 然后您会遇到段错误。

The reason that doesn't break in your tests is a combination of luck and the fact that you have a very simple, very short routine. 测试不中断的原因是运气好,而且您的例程非常简单,很短。 You're addressing memory still in your process' space and you have so few instructions, the routine probably runs in one shot. 您正在寻址仍在进程空间中的内存,并且指令很少,例程可能一次执行。

The delete keyword de-allocates the memory in the process' memory manager, but it doesn't clear it out or (usually) touch it much at all. delete关键字在进程的内存管理器中取消分配内存,但是并不能清除内存或(通常)完全不使用它。 If the memory is later used, the values will change, but until then, whatever you last set it to will stick around (more or less, this is undefined after all). 如果以后使用内存,则值将更改,但在那之前,最后设置的值将一直存在(或多或少,这毕竟是不确定的)。

Considering the fact your routine has only a few instructions, chances are high that the processor is executing them sequentially, without changing to another process in between. 考虑到您的例程只有几条指令,因此处理器很有可能按顺序执行它们,而没有在其间切换到其他进程的可能性。 This has the side effect that nothing else is likely to overwrite your memory or allocate it, so the memory remains in the process' space. 这样做的副作用是,其他任何东西都不可能覆盖或分配您的内存,因此内存保留在进程的空间中。

Because it is used again so quickly, the values you left are (likely to be) still there and it is unlikely to be in use by another process. 由于再次使用它的速度非常快,因此您留下的值(可能仍然)仍然存在,并且不太可能被其他进程使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM