1

Suppose we have the following code:

sphere * a, * b;
a = new sphere(1.0);
b = a;
b->setRadius(2.0);
delete b;
a->setRadius(4.0);
sphere * c = new sphere(5.0);
b = new sphere(3.0);
cout << a->getRadius() << endl;

What will be the outcome:

(a) 4.0
(b) 3.0
(c) A segmentation fault.
(d) Compiler error.
(e) The behavior cannot be predicted.

I dont think you'll need to see the sphere class, as its pretty obvious whats going on. Now, when we set b=a, this means bis pointing to a. Then we delete b, which means we delete what b was pointing to, and that means that a is now no longer pointing to anything. So when we try to say a->setRadius, we cant. And so I think thats a seg fault. Am I looking at this the right way?

Snowman
  • 31,411
  • 46
  • 180
  • 303
  • @Matti: no, because the correct answer is (e) and this cannot always be verified by experiments. – Konrad Rudolph Feb 21 '11 at 20:51
  • I agree with Matti, this should have just been tried. Compile and see what errors you get at run time. May be then ask what those message mean. – thecoshman Feb 21 '11 at 20:53
  • @Matti I did run it. I dunno what compiler you're using, but mine doesnt tell me "The behavior cannot be predicted" – Snowman Feb 21 '11 at 20:53
  • 2
    I don't know why someone gave him a -1. It is an honest beginner level C++ answer. It's good that he asked, because he will learn. I gave him a +1 to balance the -1 (technically he will gain +8, but we will ignore this). – xanatos Feb 21 '11 at 20:57
  • hmm this looks familiar... why not check the newsgroup? lol – RageD Feb 22 '11 at 05:38

4 Answers4

14

It's undefined behavior. It might segfault, or it might give birth to a litter of kittens. Either (and any number of other possibilities) would be conforming behavior. A very likely outcome is that it will silently corrupt your heap, with baffling consequences later on.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • Ya I think thats the right answer. In what case does code result in a seg fault? – Snowman Feb 21 '11 at 20:51
  • 3
    In other words, it will segfault if you're lucky. If you're unlucky, it will print 4.0 until 6 months after you've released it to production. – Karl Bielefeldt Feb 21 '11 at 20:52
  • `` http://stackoverflow.com/questions/1553382/pod-freeing-memory-is-delete-equal-to-delete/1553407#1553407 `` `:)` – sbi Feb 21 '11 at 21:07
2

Up to delete b; everything is ok. The next line (a->setRadius(4.0);) will trigger an undefined behaviour, because you are accessing a deleted object. The problem is that 90% of the times it will work (yes, this is a problem, because the other 10% of the times it will crash and you will lose the night finding why!)

Why this? This happens because many implementations of operator new and delete don't "ask" the memory to the OS every time they are called. They ask a big block of it and then use it a little at a time. When you delete your object, the memory is only "marked" as free, and not freed. So when you access a deallocated object, you are accessing memory that (probably) is still allocated to your process, but that you shouldn't use. In the middle some other part of your program could have allocated it and modified it, or simply the delete operator could have seen that there was so much memory "marked as free" and decided to return it to the OS, triggering a SEGFAULT if you try to access it. A "debug" version of the delete could fill it with a pattern or zero it, so that if you watch it it's more evident that it's in use or free... There are many options.

A note: I have simplified the handling of memory by new and delete. "Normally" there are some more levels of indirection. But they are irrelevant to the discussion.

On some implementations of new/delete/malloc/free on debug builds the memory, instead of being zeroed, is filled with 0xcc or 0xcdcd. This is for two reasons. If I remember correctly one is that 0xcc is the Intel instruction for the INT 3 breakpoint (and 0xcdcd is a multiple or something similar). The other is that if you watch it in a debugger, the pattern is quite obvious to see, while an "all 0x00" pattern could be more difficult to distinguish.

xanatos
  • 109,618
  • 12
  • 197
  • 280
1

With delete b;, you are deallocating the memory location which both pointers a,b were earlier pointing to. So, a->setRadius(4.0); behaviour is undefined. By undefined means it may work correctly as you expected or can result a segmentation fault or anything can happen.

Since a is a dangling pointer, a->getRadius(); would also result undefined behaviour.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
1

It's undefined behavior because you delete the sphere with which a and b are both pointing. Once deleted, they are now both pointing to an invalid sphere object (it's not even a sphere anymore, its just memory). a->setRadius(4.0) has the potential of causing a seg fault, along with a->getRadius.

To answer your multiple choice question, e would be correct.

Marlon
  • 19,924
  • 12
  • 70
  • 101