Sounds dubious, I always have optimizations turned on and have
never seen a problem with destructors not being called.
And I have. It wasn't in code I wrote, and my style wouldn't
have triggered the problem, but when I asked about it a
Microsoft newsgroup, it turned out that it is a known error, and
that it is related to the way the compiler is organized, so that
it will not be fixed anytime soon.
Are you sure you are not thinking of RVO which is perfectly
valid?
Curiously enough, it is related to RVO. The compiler suppresses
a destructor because of RVO. Even if you don't return.
MyType f(int max_tries)
{
while (max_tries > 0) {
MyType p( tentative_results )
// The following is actually some fairly
// complicated calculations...
if (max_tries < 2)
return p;
}
throw std::runtime_error( "didn't work" );
}
Instrument the constructors and the destructors of MyType, and
call the function with max_tries at 5, or something like that,
and see what happens. Basically, at maximum optimization, the
compiler "merges" p and the return value (RVO), and suppresses
the destructor of p. Except that when you loop, rather than
returning, the destructor of p isn't called, and it should be.
(In the actual code, MyType was a boost::shared_ptr. Which led
to a memory leak, and in certain cases, a bad_alloc exception.)
If you are sure that there is a VC++ bug relating to
optimizations and dtors not being called have you raised a
defect report on Microsoft connect?
I first raised the question in one of the Microsoft groups.
It's a known bug.
Do the bugs exist in VC9 or VC10?
Yes. When I found it, we immediately checked with all of the
compilers we have available. No problem with Sun CC or g++
(which no doubt have other bugs, but not this one), but a
problem in every version of VC++. According to the people at
Microsoft, it is inherent in the organization of the compiler,
and will not be fixed anytime soon. In the meantime: yet
another argument for SESE
. I'd have written the function:
boost::shared_ptr<MyClass> f(int retries)
{
boost::shared_ptr<MyClass> retval;
while (retval.get() == NULL && retries > 0) {
retval = new MyClass;
// ...
if (! retval->succeeeded())
retval.reset();
-- retries;
}
if (retval.get() == NULL)
throw ...
return retval;
}
which causes no problems (since there is no conditional return),