Perform task in destructor - c++

Is it a good technique to perform important/critical tasks of an object in the destructor?
Such as:
class MyObject{
~MyObject() {
Execute();
}
void Execute() {...}
};

Destructors are meant to be a way to automatically clean up resources held by an object when it goes out-of- scope. Nothing else should be done in destructor. But the clean up may involve critical or complex processing. Also make sure exception does not leave your destructor. That will lead to terminate your program unexpectedly if the destrcutor was originally called because of stack unwinding due to another exception.
It is good practice to provide public interface for critical clean-up/resource management, so that client code can call it and handle if any exception arises. You can check if the clean up process is done in the destructor, if not perform it, but swallow any exception thrown.
To summarize, it is NOT a good practice to perform anything at all (whether critical or not) other than resource clean up in destructor.

Generally the answer is NO. E.g. if the program crashes, destructor won't be called. There're other circumstances when dtor isn't called. Destructor is dedicated method for clean up. Class users expect such behavior.

Related

Exception handling in virtual destructor

I have a two Database class objects allocated on Stack. I inherit this database class in my personal defined class. Now Database class has a function named "Close()" which throws an exception if closing that instance of database fails. Now for client perspective i don't want Client to call close() everytime to close the connection, rather i want to declare a vitrual Desctuctor in Database class which will automatically close the connection when object goes out of scope.
Now problem i am facing is, if i create two DB objects, and now try to delete both and if close succedds for both it's fine, but if close fails for first object it throws an exception, and now second is still allocated (if dynamically allocated member objects), which results in memory leak. How to handle this situation.
you don't throw exception from the destructor what-so-ever!
See : http://www.stroustrup.com/bs_faq2.html#ctor-exceptions
Bjarne quote (can you throw exception from a d.tor):
Not really: You can throw an exception in a destructor, but that exception must not leave the destructor; if a destructor exits by a throw, all kinds of bad things are likely to happen because the basic rules of the standard library and the language itself will be violated. Don't do it.
You might not want to allocate any DB object on the stack anyway, a safe, reusable way is to use Connection Pool :
https://en.wikipedia.org/wiki/Object_pool_pattern
like this, the destruction of each conenction object iswhen the program exist, where you can handle the closing as integral part of the pool, and not in a spread way in some random functions
You probably should have a class for holding one database connection, and another class holding two instances of the first. Since I figure the creation of a database could fail as well, having each connection in its own class (with its own destructor) will handle partial construction / destruction quite nicely.
Besides, if a destructor throws, there is very little you can do (aside from logging the condition). Your application is doomed.
Do not throw exceptions from destructors, bad things happens, use a shutdown() method and call it ouside of destructor. Most C++ stuff is cleaned in destructors, if you throw from within a destructor you literally stop cleaning up things and you would end up having a C++ program in undefined state:
class Database{
std::vector<int> v;
connection c;
public:
~Database(){
c.close(); //ouch throws v don't get deallocated. (neither c)
}
};
may be changed to:
class Database{
std::vector<int> v;
connection c;
public:
~Database(){
// v deallocated here
}
void shutdown(){
c.close();
}
};
main.cpp
int main(){
Database d;
d.shutdown(); //even if d throws, d destructor will be called.
//and as consequence of d destructor also c & v
//destructors are called.
return 0;
}
since you have 2 databases
int main(){
Database d1,d2;
try{
d1.shutdown();
}catch( /** correct exception type*/){
//error handling for 1
}
try{
d2.shutdown();
}catch( /** correct exception type*/){
//error handling for 2
}
//both destructors called
return 0;
}
Chances are that if close fails, there is not good recovery path anyway, you are best off logging the error and then carrying on as if it succeeded. So I would suggest you call close in a try block in you destructor and just logging the error in the corresponding catch block. The destructor can then complete normally.
As #David mentions above, destuctors should never leak exceptions, this is because destructors are called when an exception happens and an exception in an exception causes a crash.
Exceptions should never be thrown in destructor call.
You should not call anything that can cause them there, otherwise, you're crashing your class safety.
You should add a function that checks if database object can be "closed", not an exception. If you imagine that you just can't call function in destructor that may throw exception, you will find solution.
My choice is to do not use destructors to destroy associated objects, if there is a chance that this must not be allowed.
Destructors are intended to free only internal object resources only. You can create a something like resource manager that will store pointers to all objects you need to control. These may be shared pointers. And let this class make your behavior and not objects theirself.

Is it appropriate to throw from destructor in this case

I have a class that distributes work given by the user to several threads. Something like (simplified):
class MT {
public:
MT();
void work1(/*args*/);
void work2(/*args*/);
void work3(/*args*/);
//waits until all threads complete, returns whether the work has been completed
//successfully, throws any exceptions that have been raised in the threads.
bool is_ok();
~MT();
private:
// thread pool
}
The user uses the class as follows:
void foo()
{
MT mt;
mt.work1(/*userdata*/);
mt.work2(/*userdata*/);
mt.work1(/*userdata*/);
status = mt.is_ok();
if (status) {
mt.work3(/*userdata*/);
//...
}
//...
}
The class is never part of some object, always stored on the stack.
The Problem
I want to somehow emit any exceptions that have been raised while doing work in other threads. Unfortunately, I know whether a thread has successfully completed only after joining it. Thus, I must choose between the following two alternatives:
Join the threads in the destructor of MT and throw exceptions that arose while doing work, if any. If more than one exception has been thrown, pick the one that came from the earliest task. If the destructor is called doing stack unwinding (we can check this using std::uncaught_exception, swallow any exceptions to prevent terminate().
Instruct the user to always call is_ok before the destructor.
I think the first option is cleaner, since the user is not required to call anything. However, throwing from destructor is usually very strongly discouraged. The presented arguments are:
Throwing from destructors is dangerous, because this might happed during stack unwinding and lead to terminate().
Even if the above is addressed, throwing or not throwing depending on whether stack is being unwound is a substantial change of behavior and should be discouraged.
Exceptions signify that a postcondition have not been met. The postcondition of a destructor is resource cleanup, this must be possible in any circumstances.
Somehow I am inclined to think that the above arguments don't apply here:
I handle the stack unwinding problem properly
Due to the usage pattern, any exceptions that exit from foo means that work has been failed. Throwing or not throwing in the destructor is not a substantial change of behavior.
The postconditions of the destructor are not only resource cleanup, but also that the work has been completed successfully. Thus an exception should be appropriate.
Questions
Do you think throwing from destructor is appropriate in this case?
No, don't throw from the destructor. Call is_ok, catch and ignore. Same as close() for streams.
The user can call is_ok if they want to be sure that the work has been completed, and it will throw an exception on failure.
In practice this is rarely inconvenient. It will be if the user writes a function with multiple return points, but (unfortunately) that's a problem they just have to deal with because C++ doesn't provide a means for you to do it for them. If you think this is anti-social, well, look at what happens if you destroy a std::thread in C++11 without first either joining it or detaching it. You're beating that :-)
So, user calls is_ok on all non-error exit paths. User doesn't bother calling it when there's already an exception, because they can't deal with another one anyway. Again, this is the same as close() for streams: if you want to see errors from writing your buffered stream then you just have to close or flush explicitly.
Even if the above is addressed, throwing or not throwing depending on
whether stack is being unwound is a substantial change of behavior and
should be discouraged.
It's also not possible to do correctly, at least in C++03. I don't know whether C++11 changes anything in this respect, but std::uncaught_exception does not tell you what you need to know, as Herb Sutter explains.
From your link to cppreference.com:
Any exception thrown while std::uncaught_exception() == true calls std::terminate.
I'm pretty sure this is false. terminate is called if an exception escapes a destructor that is called as part of stack unwinding, but it isn't called just because a destructor throws and catches an exception during unwinding.
If the caller thinks they can do something useful with an exception thrown in a destructor, then they can write a helper class that calls is_ok in its destructor, and put that over your object. If you think there's something useful that your class can do with the same exception then you can do something other than merely ignore it in your destructor, but you still shouldn't allow it to leave the destructor.

Should one put output operations into a destructor?

I've got a class that collects and processes some data during the execution of the program, let's call it dataCollectionInterface. When the program terminates (or rather: a dataCollectionInterface object goes out of scope) some final processing and output of (some of) the collected data needs to be done.
The question now is: should I put this final processing and output (to files) into the destructor of dataCollectionInterface (or call it from within the destructor)? Or should I provide a public member routine (doFinalProcessing) that needs to be explicitly called by the main program?
Putting it into the destructor would be a lot more convenient (no need to worry about safeguards against data modulation after a call to doFinalProcessing etc.), but are there downsides, e.g. with respect to the handling of possible exceptions from the output operations?
You should not be throwing any exceptions from the destructor, So better to do it in a public function, rather than the destructor if your operations can throw exceptions and you need to do the exception handling for them.
Though, If you can rather handle all your exceptions within the destrucotr itself without throwing them out from the destructor, then you might go for the first mechanism as well, I see no harm if you can reliably do so.
A destructor cannot fail. Thus, you should not put any operations which
might fail (and output can fail) in a destructor; what do you do if it
fails.
There are exceptions, when the operation isn't really relevant to the
overall functionality of the program (logging output, for example), or
when it is a safeguard (ofstream will close the file in the
destructor, ignoring any errors), or when it is part of an operation
which will be later "annulled": a non-committed transation may close an
output file, for example, knowing that because the transaction is not
committed, the file will later be deleted. But they are just that:
exceptions.
Others are correct about destructors not throwing, but that shouldn't mean not to do it in a destructor. Nor should it mean that there should be no diagnostics. But you definitely should put it in the destructor.
First of all, the reason that you should put it in the destructor is less about immediate convenience but because zombies are evil. Objects that have finished their useful lifetime but still exist to be accidentally encountered and used are the bane of developers. Young developers come in and touch them when they shouldn't causing all sorts of problems. Complexity explodes because you now have to check if you've cleaned up things properly. Exception handling is now not automatic, as it would be in a destructor. Do you really want to write try/catches everywhere you use the object just because something unrelated might throw and you have to clean it up properly? Do you want to write "ifs" in all your code for that class to make sure they aren't using a mostly dead object?
Two-phase initialisation or destruction are code smells that you are not using ctors/dtors correctly. Use them to automate all of your object's lifetime (RAII), and you will never have the code fragility that zombies bring.
So, how do you do it if the output operation might throw?
Wrap your use of possible throwing calls in a try / catch.
In the constructor of the object, take an optional function callback to an error handling routine from the user.
In the dtor, when an exception is caught, call the callback (if they gave you one) with whatever diagnostic you can provide
Wrap the callback call in a try/catch too, as you have no idea what others will do
Do nothing if the callback throws - they had their chance
It's really that simple. Don't ever let zombies roam, even if you have special exception-possible code in dtors. Instead, provide a means to handle that in an abstract manner. A single special case of cleanup is always better than the combinatorial explosion of special cases when zombies are let free.
I would provide both: destructor with some default behaviour (catching all exceptions and probably silent about possible problems) and a public member routine with extended diagnostics. What approach to use is up to user of the class. Internally the destructor may call the routine with try/catch block, if the routine may throw. The routine should be idempotent (second call should do nothing)

Destructor that calls a function that can throw exception in C++

I know that I shouldn't throw exceptions from a destructor.
If my destructor calls a function that can throw an exception, is it OK if I catch it in the destructor and don't throw it further? Or can it cause abort anyway and I shouldn't call such functions from a destructor at all?
Yes, that's legal. An exception must not escape from the destructor, but whatever happens inside the destructor, or in functions it calls, is up to you.
(Technically, an exception can escape from a destructor call as well. If that happens during stack unwinding because another exception was thrown, std::terminate is called. So it is well-defined by the standard, but it's a really bad idea.)
Yes.
Look at the std::fstream class in the standard library for an example.
close() could potentially throw an exception.
The destroctor can call close() but the destructor does not throw (it will swallow any exceptions).
The concept is that if the destructor calls any methods that can throw then these methods should be public. Thus if the user of your object wants to check for exceptions they can use the public methods and handle the exception. If they do not care about the exception then just let the destructor handle the problem.
Going back to the std::fstream example.
{
std::fstream text("Plop");
// Load Text.
// I don't care if the close fails.
// So let the destructor handle it and discard exceptions
}
{
// If this fails to write I should at least warn the user.
// So in this case I will explicitly try and close it.
try
{
std::ofstram password("/etc/password");
// Update the password file.
password.close();
}
catch(...)
{
Message.ShowDialog("You failed to update the Password File");
}
}
You can find some examples here: https://software.intel.com/sites/products/documentation/doclib/iss/2013/sa-ptr/sa-ptr_win_lin/GUID-D2983B74-74E9-4868-90E0-D65A80F8F69F.htm
If an exception leaves destructor during stack unwinding of another exception being propagated, then std::terminate() is called.
When no stack unwinding is in progress, an exception can leave destructor without std::terminate() getting called. However, for objects allocated on heap this will result in memory leak because "operator delete" will not be called for the object who throws exception out of its destructor. Surprisingly, the destructor of base class still gets called in this case: What happens to base class destructor if a derived class destructor throws an exception
If the exception is catched inside the destructor (so that the exception does not leave the destructor), then no problem even if stack unwinding of another exception is in progress. This case is described more deeply here: http://bin-login.name/ftp/pub/docs/programming_languages/cpp/cffective_cpp/MEC/MI11_FR.HTM
Simple answer, never allow an exception from a dtor!
The complicated answer. You only get really nailed if the exception escapes the dtor while another exception is active. The normal case for this is when you are already unwinding the stack from another exception and the object in question is destroyed. In that case if the exception escapes the dtor then std::terminate is called, note you can put in your own handler for std::terminate by calling std::set_terminate. The default implementation of std::terminate is to call abort.
To complicate things more, most functions that want to make any guarantee about their exception safety, mainly the basic guarantee or the strong guarantee, rely on the underlying types to themselves not throw in their dtor*
The real question is, what state would your program be in when this error occurs? How can you recover? Where should this recovery be handled? You need to look at your specific case and work these issues out. Sometimes it's just fine to catch the exception and ignore it. Other times you need to raise some red flags.
So the answer is: it allowed by C++ to throw an exception in a dtor, but you shouldn't ever allow it to escape.
*Here's a brief synopsis of the exception guarantees (here's a much longer article)
Recap: Briefly define the Abrahams exception safety guarantees (basic,
strong, and nothrow).
The basic guarantee is that failed
operations may alter program state,
but no leaks occur and affected
objects/modules are still destructible
and usable, in a consistent (but not
necessarily predictable) state.
The strong guarantee involves
transactional commit/rollback
semantics: failed operations guarantee
program state is unchanged with
respect to the objects operated upon.
This means no side effects that affect
the objects, including the validity or
contents of related helper objects
such as iterators pointing into
containers being manipulated.
The nothrow guarantee means that
failed operations will not happen. The
operation will not throw an exception.
You may find this page from C++ FAQ Lite to be informative. The basic answer is, "don't do it." Where exactly do you plan to catch this exception? Whatever you plan on doing when you catch that exception, just do it with a function call instead or something (e.g. log it or set a flag to warn the user or whatever). Throwing exceptions from the destructor runs the risk of causing your entire program to terminate.

Shall I place try...catch block in destructor, if I know my function won't throw exception

I know destructor shouldn't not throw exception.
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13
I have the following code :
~a()
{
cleanup();
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
In my static source code analysis, it complains that I shall call the cleanup function in this way :
~a()
{
try {
cleanup();
}
catch(...) {
// What to do? Print out some logging message?
}
}
// I do not expect exception being thrown in this function.
// If exception really happen, I know that it is something not recoverable.
void a::cleaup()
{
delete p;
}
I am not sure whether this is a good practice, to place try...catch block in destructor, whenever it calls functions. As :
(1) If cleanup function able to throw exception, I know something bad had happened. I prefer it to be fail-fast. That is, just let the whole system crash, and let the programmer debugs it.
(2) Overhead occur while entering and exiting try...catch block.
(3) The code look cumbersome, with a lot of try...catch block around classes' destructor.
I may miss out some other points, why try...catch block should be in place.
Thanks.
Since delete won't throw, neither will cleanup and as such there is no need to put the call in try-catch.
Since your static analysis tool is probably having a hard time figuring that out, perhaps you could help it out (it's only a guess though) by declaring cleanup as no-throw.
void cleanup() throw();
Maybe you can be more precise about your cleanup function. Does the cleanup() function throw an exception intentionally, if only in very rare circumstances? Then you should definitely handle the case in your destructor because, even if rare, exception-throwing is expected behavior of cleanup().
At the very least, your exception handling code could leave your program in a well-defined state that would allow you to end your program gracefully.
Or do you mean cleanup() may throw e.g. an OutOfMemoryException or another runtime exception that you never handle anywhere else? Then I would omit the exception handling in the destructor as well. In such unusual circumstances, your application could probably not run its error handling code anyway. You should do everything possible to make sure even such an exceptions gets reported or logged properly.
Edit:
Now that you have shown the implementation of cleanup, Neil has already answered your question. delete p must not throw, hence a::cleanup will not throw as long as p's destructor does not throw.
Surely the issue is really in the destructor of p. When, in cleanup(), you say
delete p;
delete itself cannot throw, therefore the exception must comne from p's destructor. It is in that destructor you need to worry about using a try block, not the one for a.
There's not usually any point in throwing an error due to memory allocation or deletion. It either works or not, and you can spend a ton of work handling silly errors without getting any benefit.
You might want to do this in specific cases but it's nor done much in practice and when there's question you usually want to use debugger or more full instrumentation.
Fundamentally, it is not safe to throw an exception whilst already handling an exception.
If your destructor is being called whilst the stack is unwinding, and another exception is thrown, then your thread can be terminated immediately on some systems such as Symbian; that your code was planning to catch the exception won't stop that termination - your code won't even be called. Your thread certainly will be terminated if your exception escapes the destructor.
So try {} catch(...) {} in a destructor is not portable and is certainly tricky.
The sound advice is never call code that could throw an exception in cleanup code such as destructors and any function that might be called from a destructor, such as 'cleanup()', 'close()' or 'release_something()'.
The original poster also queries the performance of try-catch. Early in the adoption of C++ exceptions, exception handling code was reasonably expensive; these days, your compiler almost certainly uses zero-cost exceptions, which means that an exception not thrown adds no runtime performance penalty to the code (but of course does slightly increase the binary size of the program).
I never use this, but exception safety purists will say that your cleanup() function may throw without you expecting it. So this pattern is a technique for extra safety.
However, a cleanup function should not throw in the first place. So I would put any exception handling inside cleanup(), not in the destructor itself.