Question

In Effective C++ 3/E, I read this:

This is exception unsafe code:

class Test { };
void foo(const std::shared_ptr<Test> &ptr, int i);
int bar();
...

foo(std::shared_ptr<Test>(new Test), bar());

Because compiler can implement like this:

  1. run new Test
  2. call bar() <-- if bar() throws exception, the object of Test allocated by new Test cannot be deleted.
  3. call constructor of std::shared_ptr<Test>
  4. call foo()

But in this case, compiler can know there's memory leak. Can't compiler do delete automatically if exception is thrown?

In addition, compiler does automatically delete in that case:

Test *p = new Test;

that is implemented like this:

  1. call operator new to allocate memory
  2. call constructor of Test. If constructor throws exception, memory is automatically deleted.

Why compiler doesn't do in first case, unlike second case?

Was it helpful?

Solution

The compiler cannot normally know that there is a memory leak. Once the code returns from the constructor of Test, the compiler must assume that the object has been fully and correctly constructed, which could (and often does) mean that the constructor has registered a pointer to it somewhere, and that other code will expect to find it.

The standard could have specified that an exception will cause delete to be called on all objects newed in the complete expression it passes through. There are a number of historical reasons why this wasn't even considered. And today, it would probably break too much existing code.

The standard also could have imposed a strict ordering on the evaluation of an expression. This would remove a lot of issues of undefined behavior, and make code more deterministic (so tests are more reliable). Historically, C didn't take this route because of its impact on optimization; C++ has kept the rule.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top