The memory created using the operator new must be explicitly deallocated. Since the objects *pJ and *pK are never destroyed by the code, the desctructors are never called.
Destructors are called when one of the following events occurs: A local (automatic) object with block scope goes out of scope. An object allocated using the new operator is explicitly deallocated using delete . The lifetime of a temporary object ends.
No. You never need to explicitly call a destructor (except with placement new ). A class's destructor (whether or not you explicitly define one) automagically invokes the destructors for member objects. They are destroyed in the reverse order they appear within the declaration for the class.
A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ). For example, the destructor for class String is declared: ~String() .
The following code demonstrates a weird problem I have in a Turbo C++ Explorer project. One of the three stack objects in D::D() is not destroyed after going out of scope.
This only happens if compiled in release mode, the auto_ptrs a_ and b_ are of different types and the exception thrown doesn't inherit from std::exception. It appears to work just fine in VC++ 2005 and C++ Builder 2009. I did install the BDS2006 Update 2, the hotfix rollup and hotfix 12.
Is it my code or the compiler? Do you know of a fix? Not being able to reliably use auto_ptr in a VCL project would be quite inconvenient.
#include <memory>
#include <stdexcept>
#include <iostream>
typedef std::exception my_error; // will work fine if replaced with line below
//class my_error : public std::exception {};
class A {};
class B {};
class C
{
public:
C(int id) : id_(id) { std::cout << "C::C() " << id_ << std::endl; };
~C() { std::cout << "C::~C() " << id_ << std::endl; };
private:
int id_;
};
class D
{
public:
D()
{
C c1(1);
C c2(2);
C c3(3);
throw my_error();
};
private:
std::auto_ptr<A> a_;
std::auto_ptr<B> b_; // will work fine if replaced with line below
// std::auto_ptr<A> b_;
// std::auto_ptr<C> c_; // see expected output
};
#pragma argsused
int main(int argc, char* argv[])
{
try
{
D d;
}
catch (...)
{
std::cout << "caught exception" << std::endl;
}
return 0;
}
Expected:
C::C() 1 C::C() 2 C::C() 3 C::~C() 3 C::~C() 2 C::~C() 1 caught exception
Got:
C::C() 1 C::C() 2 C::C() 3 C::~C() 2 C::~C() 1 caught exception
Got (with line '// std::auto_ptr<C> c_;
' uncommented):
C::C() 1 C::C() 2 C::C() 3 C::~C() 1 caught exception
Edit: Made suggested changes
Edit 2:
I just tested it with C++ Builder 2007 (11.0.2902.10471), which shows the same problem. The release configuration works as soon as I check the "Debug information" box in Project -> Options -> C++ Compiler -> Debugging. It surprises me that the executable gets smaller with "Debug information" enabled (down to 31.5 KB from 39.5 KB ).
Edit 3:
In Turbo C++ Explorer (C++ Builder 2006) (10.0.2288.42451) the release configuration works if I uncheck the "Inline function expansion (-vi)" box in Project -> Options -> C++ Compiler -> Debugging. Replacing the first line (#include <memory>
) with the following code makes it work, too.
#pragma option push -vi-
#include <memory>
#pragma option pop
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With