views:

132

answers:

9

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;

Thanks!

A: 

Accessing deleted object is an undefined behavior. Anything can happen

VJo
+2  A: 

Undefined behavior is just that, undefined. It can even work if it so pleases.

Noah Roberts
A: 

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).

GWW
+9  A: 

I expected a seg-fault after 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.

Ed Swangren
+1: But, you *should* expect that with undefined behavior, eventually, whatever you expected will be wrong. ;-)
Chris
Haha, yes, very true.
Ed Swangren
Hmmm, someone downvoted this. I wonder why...
Ed Swangren
+1  A: 

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.

Mario
Thanks, your explanation was really clear, and confirmed what I thought.
Hasung Chier
A: 

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.

Steve Townsend
No, the pointer initially points to a valid object, the OP is simply dereferencing it after deleting it.
Ed Swangren
Again, after your edit, you are not on target here. The pointer is valid, you seem to be missing the line "e = new Test();". The problem is dereferencing the pointer after calling delete on it.
Ed Swangren
@Ed Swangren - thanks - my point in the first code sample is that there is more than one reason why a pointer var can be unusable. Understanding ownership of the memory at each juncture is the key. The broader point is that the less you use `new/delete` by hand, the less you have to worry about this particular issue.
Steve Townsend
A: 

run it under valgrind. it will tell you that you did a bad thing

pm100
A: 

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 deleted e, doesn't not undo that mapping.

So you are still accessing memory that your application has permission to use from 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. Then you get a seg fault.

dmckee
A: 

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. 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.

peachykeen