Consider the following class:
struct A
{
A(){ std::cout << "A()" << std::endl; throw std::exception(); }
~A(){ std::cout << "~A()" << std::endl; }
};
A a;
int main(){ }
DEMO
The Standard promised that the appropriate deallocation function will be called N4296::5.3.4/20 [expr.new]:
If any part of the object initialization described above78 terminates
by throwing an exception, storage has been obtained for the object,
and a suitable deallocation function can be found, the deallocation
function is called to free the memory in which the object was being
constructed,
But what about destructor? In that example it was no called. So, did we get UB?
Destructors are called for all successfully initialized objects.
Otherwise there would have had to be default zero-initialization (some overhead) in order to be able to assume anything in a destructor.
The A object whose constructor throws, is not successfully initialized. So its destructor is not executed. However, if it had any class type sub-objects (base class sub-objects, data members) that had been successfully initialized prior to the exception, then destructors would be called for these.
And no, throwing from a constructor is not UB.
On the contrary it's the common way of signalling construction failure, and it ensures that the caller will either have a successfully initialized and presumably useable object, or else (just) an exception.
History. Originally C++ didn't have exceptions. Construction failure was then signalled by assigning 0 to this. I can't recall how that interacted with allocation, but presumably the same way that an exception now does, namely a guaranteed deallocation. But with this scheme you could only fail construction for dynamically allocated objects…
Destructors are not same as deallocators. Whenever a variable goes out of scope the object referenced to the variable is deleted. In the problem you have given the object is a global variable, so it will be deleted when the program terminates.
Related
I don't understand why the destructor was called (the place of this call in the code below )
and if the destructor was called, why the function Print() could be called?
The code:
class Entity
{
public:
Entity()
{
std::cout << "Ctor Call" << std::endl;
}
~Entity()
{
std::cout << "Destroy Call" << std::endl;
}
void Print()
{
std::cout << "Print me" << std::endl;
}
};
int main()
{
Entity* ent;
{
std::shared_ptr<Entity>sharedPtr = std::make_shared<Entity>();
sharedPtr->Print();
ent = &(*sharedPtr);
} //after this line the destructor was call
ent->Print(); // the print is success
std::cin.get();
}
Yes, the destructor is called when the shared pointer goes out of scope (and thus gets destroyed itself). The reason that the subsequent Print() method call is successful is that calling a method on a destructed object is an undefined behaviour, so it doesn't need to necessarily crash. The object itself could still be lying around and the method call may be successful, albeit there is absolutely no guarantee. In this case the chances are even a bit higher because the method doesn't actually use any data from the instance, but simply calls library functions.
Please note that here copying the underlying address held by the shared_ptr doesn't make it increase its internal reference count, because this is done circumventing the "official" means of getting a copy from the shared pointer, in fact, from the std::shared_ptr reference:
shared_ptr objects can only share ownership by copying their value: If two shared_ptr are constructed (or made) from the same (non-shared_ptr) pointer, they will both be owning the pointer without sharing it, causing potential access problems when one of them releases it (deleting its managed object) and leaving the other pointing to an invalid location.
If the copy was obtained by copying the shared_ptr, then the object would not have been deleted.
why the function Print called without crash
Because there is no guarantee that if your code produce Undefined Behavior (and your does indeed) then it has to crash. It could even look that your program succeded and that is probably the worst side of UB.
The destructor was called because the object ent was created inside a local scope, so after going out of scope, the destructor should be called. For more informatoin about the shared pointers you may refer to this question
This question already has answers here:
Destructor being called twice when being explicitly invoked
(10 answers)
Closed 8 years ago.
On calling desctructor explicitly, it is executed two times. What's the reason for that?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A() { cout << "A's constructor called " << endl; }
~A(){
cout<<"A's desctructor called "<<endl;
}
};
int main()
{
A a;
A b;
a.~A();
}
Output:
A's constructor called
A's desctructor called
A's desctructor called
Well, you called it for 'a', and then 'the language' called it again for 'a' when the object went out of scope. And then, of course, 'the language' called it for b. By 'the language', I mean, of course, the very basic rule that automatic-scope objects are constructed as their scope initialize, and destructed when their scope ends.
Using explicit calls to destructors is rarely a good idea.
You shouldn't call the destructor by hand, it will get called automatically when the object goes out of scope.
The only place to manually call destructors is when you're writing your own allocator, but that is quite an advanced topic, so the rule of thumb would be to never call the destructor by hand.
[basic.life]/8:
If a program ends the lifetime of an object of type T with […]
automatic (3.7.3) storage duration and if T has a non-trivial
destructor, the program must ensure that an object of the original
type occupies that same storage location when the implicit destructor
call takes place; otherwise the behavior of the program is undefined.
Hence we cannot explain the behavior of your program in general, but we could say "For your implementation a particular execution behaved as if the destructor was called two times."
When a variable goes out of scope, its destructor is implicitly called.
If the there is no object of the appropriate type there, the behavior is undefined. Typically the compiler generates code that would call the destructor and does so blindly, as that makes the 'defined behavior' path efficient and simple, and the 'undefined behavior' path is considered your fault.
So what you are seeing is a symptom of undefined behavior. Your call of the destructor does not mean the compiler will not try to destroy the object.
In fact, if your object was slightly more complex, it could easily lead to a crash.
Don't call the destructor of an object directly unless you used placement new (a variant of new that constructs an object and does not allocate any memory) or the equivalent on it, and don't use placement new unless you really know what you are doing.
There is another valid use, where you destruct and reconstruct in the same place, but that is dangerous, usually a bad idea, and hard to get right.
I'm calling the destructor to deallocate memory but it is not deleting my object. What is the reason behind it?
my code is like this:
class A
{
public:
int a;
A()
{
cout << "a" << endl;
}
};
class B :public A
{
public:
int b;
B()
{
cout << "b" << endl; a = 10; b = 20;
}
~B()
{
cout << a << b << endl;
}
};
and I am using it like:
int main()
{
{
B b;
b.~B();
b.b=100; // why this step is executed?
}
int x;
cin>>x;
return 0;
}
i m calling destructor to deallocate memory
Why? At language level destructor does not deallocate memory occupied by the object itself.
A non-trivial destructor ends object's lifetime, but it doesn't end the object's storage duration. This means that memory remains allocated, it just becomes "raw" (uninitialized).
So, in that sense it is destroying your object.
Meanwhile, a trivial destructor has no effect at all. Even if you call it explicitly, the object's lifetime does not end.
In your case the destructor B::~B is non-trivial though, which formally means that by calling it you ended your object's lifetime. You destroyed it as much a local object can be destroyed. But the memory remains. Attempting to access that memory as a B object simply leads to undefined behavior.
In fact, there's no way to manually deallocate memory occupied by a local object. Local memory is always deallocated automatically.
You do not call a destructor like that (well, you can but it's generally not done).
For automatic variables like your b, the destructor will be called at some point when the variable goes out of scope. You don't ever need to call the destructor explicitly.
For objects allocated on the heap with new, the destructor will be called after you delete them. In this case, you also don't call the destructor explicitly.
C++03 states in 12.4 Destructors:
Destructors are invoked implicitly:
for a constructed object with static storage duration (3.7.1) at program termination;
for a constructed object with automatic storage duration (3.7.2) when the block in which the object is created exits;
for a constructed temporary object when the lifetime of the temporary object ends;
for a constructed object allocated by a new-expression, through use of a delete-expression;
in several situations due to the handling of exceptions.
Destructors can also be invoked explicitly.
Note: explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specific addresses using a new-expression with the placement option. Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
You especially don't do what you're trying to do since the destructor will be called twice, once explicitly by you and once implicitly when b goes out of scope. From that same section of the standard:
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended. Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
This text remains unchanged in the latest draft of C++11 that I have (n3225, November 2010) and it's unlikely it would have changed in essence between that and approval in August 2011.
What you're doing is actually invoking undefined behavior ... just because you've called the destructor, does not mean that the memory is zeroed out or necessarily "reclaimed" and inaccessable (especially in the case of an automatic variable that was allocated on the stack and not the heap). It could be, but that is left up to the implementation, and typically that is not done due to performance reasons, which is typically the reason for using C++ in the first place. Therefore you can theoretically access the values at the memory address that the object was occupying after calling the destructor ... but again, it's undefined behavior, and you can run into pretty much anything from a segmentation fault, to a silent error that corrupts memory somewhere else, etc.
It's executed because you wrote the code that said you wanted it to happen. The compiler is simply doing what you told it to do.
What you're doing probably doesn't "deallocate memory," as you suggested it would. Instead, it just calls the destructor. Destructors don't deallocate the memory occupied by the objects they're called on. They deallocate memory allocated by the object (such as by calling destructors of member variables, or calling free or delete on other things), but the memory of the object itself is deallocated elsewhere, either by the internal workings of the delete statement, or by the compiler when cleaning up automatic variables (which is what your B b declaration represents). Even the closing of the scope block probably doesn't deallocate any memory for b; compilers usually figure out how much stack space they'll need for an entire subroutine and allocate it all upon entry. The memory occupied by that B object is reserved for b upon entry to the inner scope, and upon exit, the destructor is called automatically.
Your object has been destroyed but its memory space is still around until it goes out of scope.
Why wouldn't? Your object has been destroyed but its memory space is still around until it goes out of scope, where it will be destroyed again by the way. It's undefined behavior to do what you do.
Destructors were not designed to call them explicitly. Basically it is just another (special) method of class.
If you want to Uninitialize your object and then still be able to use it you could make our own method:
class B: public A
{
public:
int b;
B() {cout<<"b"<<endl;a=10;b=20;}
~B() {Release(); cout<<a<<b<<endl;}
void Release() { cout<<"Releasing B"; b = 0; }
};
int main()
{
{
B b;
b.Release();
b.b=100; // why this step is executed?
}
int x;
cin>>x;
return 0;
}
Otherwise B will be deleted when out of scope:
int main()
{
{
B b;
b.b = 100; //OK
}
b.b = 100; //compile time error
int x;
cin>>x;
return 0;
}
How does C++ ensure that destructors are called for stack assigned objects? What happens to the destructor function (or a pointer to it) when I assign dynamic memory as follows:
class MyClass {
public:
~MyClass()
{
std::cout<<"Destructor called."<<std::endl;
}
MyClass()
{
std::cout<<"Constructor called."<<std::endl;
}
};
....................................................................
//Limit scope for example
{
MyClass instance;
}
The constructor and destructor are both called. What's going on here?
The compiler inserts a call to the destructor for the object at an appropriate position.
You wouldn't wonder why this
{
int i;
}
creates and destroys i automatically, would you? C++ does a lot to allow you to create types that behave just like built-in types. And just like with built-in types, in C++ (other than in, say, Java or C#), this
{
MyClass instance;
}
doesn't just define a reference that might be bound to null or some actual object. It creates an actual object.
Object creation comes in two steps: First (upon entering the scope) the raw memory is provided. Then (when the object definition is encountered) the constructor is called. For built-in types no constructor is called. If you don't initialize a built-in variable, it has a random value. (Actually it's whatever the bit pattern was at the memory provided in step #1.) Object deletion, too, comes in two steps: First, the destructor is called (again, not for built-ins), then the memory is returned to the run-time system.
(Note that providing and deleting memory for stack variables usually is as cheap as incementing/decrementing a register.)
The constructor is called as soon as the variable is created. As for the destructor, the compiler emits code at the end of scope to call the destructor. To get a feel for this, try using a 'goto', or switch/case construct to prematurely exit the scope, and watch the compiler complain.
Yes, both the constructor and destructor are called. And even more important:
{
MyClass instance;
throw "exception";
}
in this example, the destructor is also called. That is why I always prefer to allocate my objects on stack (or at least wrap the dynamic allocations with a stack-allocated guardians).
The constructor is called because you're creating an object. The destructor is called because your cleaning up that object. Remember, in C++, objects declared on the stack are automatically cleaned up when their containing scope goes away.
Well, it did not call the destructor just after constructor.
It calls it when it about to terminate the programme.
int main() {
MyClass obj;
cout<<"testing....1"<<endl;
cout<<"testing....2"<<endl;
return 0;
}
ans:
Constructor called.
testing....1
testing....2
Destructor called.
I was debating with some colleagues about what happens when you throw an exception in a dynamically allocated class. I know that malloc gets called, and then the constructor of the class. The constructor never returns, so what happens to the malloc?
Consider the following example:
class B
{
public:
B()
{
cout << "B::B()" << endl;
throw "B::exception";
}
~B()
{
cout << "B::~B()" << endl;
}
};
void main()
{
B *o = 0;
try
{
o = new B;
}
catch(const char *)
{
cout << "ouch!" << endl;
}
}
What happens to the malloced memory o, does it leak? Does the CRT catch the exception of the constructor and deallocate the memory?
Cheers!
Rich
A call to
new B();
resolves in two things:
allocating with an operator new() (either the global one or a class specific one, potentially a placement one with the syntax new (xxx) B())
calling the constructor.
If the constructor throw, the corresponding operator delete is called. The case where the corresponding delete is a placement one is the only case where a placement delete operator is called without the syntax ::operator delete(). delete x; or delete[] x; don't call the placement delete operators and there is no similar syntax to placement new to call them.
Note that while the destructor of B will not be called, already constructed subobjects (members or B and base classes of B) will be destructed before the call to operator delete. The constructor which isn't called is the one for B.
When an exception is thrown from the constructor, the memory allocated by new is released, but the destructor of class B is not called.
In this case, your object, o, does not actually get constructed, and the memory allocated by new is freed. As such, the destructor does not get called. So you do NOT need to call:
delete o;
An interesting design pattern is RAII -- Resource Acquisition Is Initialization. In this pattern, you use a constructor to encapsulate the acquisition of a resource, and release the resource in the destructor. If the resource can not be acquired, you throw in the constructor -- much like your example. Thus if you have a valid object, you have the resource.
If the object is constructed, then you have successfully acquired the resource. This means that for the life of the object, you own the resource. When the object is deleted, the resource is released. If the object is never constructed, then you never acquired the resource. See wikipedia:
http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
From the C++ 2003 Standard 5.3.4/17 - New:
If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object’s memory to be freed. [Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. ]
So there may or may not be a leak - it depends on whether an appropriate deallocator can be found (which is normally the case, unless operator new/delete have been overridden).In the case where there's a suitable deallocator, the compiler is responsible for wiring in a call to it if the constructor throws.
Note that this is more or less unrelated to what happens to resources acquired in the constructor, which is what my first attempt at an answer discussed - and is a question that is discussed in many FAQs, articles, and postings.