How to handle a file destructor throwing an exception? - c++

It's important to detect an error when you close a file to which you were writing, because the last part of your data could be flushed during the close, and if it's lost then your last write effectively failed and someone should know about it. The destructor for a file object is a nice place to automatically close it, but people say not to throw exceptions from destructors, so if the close fails then how do you know about it?
I've heard people recommend calling the close() method of the file manually. That's sounds nice, except what happens if the close() methods of multiple files all fail in a situation like this:
MyFile x(0), y(1), z(2);
x.close();
y.close();
z.close();
?
Well, it seems that if the close() method of 'x' throws an exception then you've done well to uphold the rule to avoid throwing exceptions in the destructor of 'x', except now you're good-intentioned early calls to the close() methods of 'y' and 'z' won't execute until their destructors. So, then when the close() method of 'y' is called in the destructor of 'y' or the close() method of 'z' is called in the destructor of 'z', and if they do throw exceptions then you're screwed.
Is there a reasonable way to not be screwed in such a situation?

Yes, catch the exception thrown from close in the destructor.
It is vitally important that a C++ destructor not throw an exception period. To do otherwise will mess up many of the resource management routines within virtually every available library.
True, you lose the failure information in this case by catching the exception. If the user is actually concerned about the error, they can manually call close and deal with the exception.

This is a FAQ item: 17.3 How can I handle a destructor that fails?
Edit:
Well, it seems that if the close()
method of 'x' throws an exception then
you've done well to uphold the rule to
avoid throwing exceptions in the
destructor of 'x', except now you're
good-intentioned early calls to the
close() methods of 'y' and 'z' won't
execute until their destructors.
No. Dtors for y and z will be called when the stack unwinds provided you have a try-catch block installed around the MyFile ... z.close() part. A better idea would be to put a close in the dtor as well. The dtor for x will not be -- so some cleanup is in order in the catch block.
I suggest you run the following program to better understand dtor-calls in the case of an exception (once as-is and again by uncommenting the S x line):
#include <iostream>
using namespace std;
struct s {
s(int i = 0) : m_i( i ) { cout << __func__ << endl; }
~s() { if (m_i == 0) except(); cout << __func__ << endl; }
void except() { throw 42; }
int m_i;
};
int main() {
try
{
s y(2), z(3);
/* s x */
y.except();
}
catch (...) { cout << "exception\n"; }
cout << "stack unwound\n";
}

You shouldn't throw from a destructor -- so:
If close had calls that threw exceptions, I would swallow them and do one of the following:
Option 1: Write out an error message and kill the program.
Option 2: Make the error available via a wrapper object (I would probably do this) or a global variable or (prefferably) a variable that is in thread local memory.
Option 1 and 2 both seem reasonable here.
With option 2 and the wrapper you would do:
WrapFileX.close();
WrapFileY.close();
WrapFileZ.close();
if(WrapFileX.hasError || WrapFileY.hasError || WrapfileZ.hasError)
{ //log
exit(1)
}

In this example, I don't see why anything should be thrown. I don't think that this scenario is exception-worthy at all. In theory, the close didn't fail, it just failed to write the rest of the buffer; which isn't a very exceptional situation. It can be handled and should be handled, unless there's a reason that the file needs to be closed right this instant.
I, personally, would just have my close() function block until the writes have completed, then continue with closing.

The rule as I see it is:
If you don't care about the exception then let the destructor do the close work (and catch and discard the exceptions). If you do care (AND can do something about it) then close manually and catch the exception and do the appropriate work.
{
std::fstream X("Plop_X");
std::fstream Y("Plop_Y");
std::fstream Z("Plop_Z");
// Do work
try
{
X.close();
}
catch(Plop const& e)
{
// Fix the exception
// Then make sure X closes correctly.
// If we can't fix the problem
// rethrow
if (badJuJu)
{ throw;
}
}
// Don't care about Y/Z let the destructor close them and discard the exception.
}

try {
x.close();
y.close();
z.close();
}
catch {
//do what ever you need to do here, then close() what' you'll need to close here
}
That's what i would do ,the point is maybe you don't know which one throw the exceptions, and which one left for closing.

First, MyFile's destructor should catch the exception (and that's an incredibly strong "should" - it's not "must" because the behaviour if it doesn't is well-defined, but it's almost never desirable):
~MyFile() {
try {
close();
} catch(...) {}
// other cleanup
}
Next, callers should decide whether they want to handle the error. If they don't, then they can just let the destructor be called. If they do, then they have to call close themselves. If your example of three files, supposing that once one of them has failed you don't care about the others, you can do this:
MyFile x(0), y(1), z(2);
try {
x.close();
y.close();
z.close();
} catch(...) {
std::cerr << "something failed to close\n";
}
If you want to know exactly which failed, you need to ensure that all three close functions are actually called:
MyFile x(0), y(1), z(2);
try {
x.close();
} catch(...) {
std::cerr << "x failed to close\n";
}
try {
y.close();
} catch(...) {
std::cerr << "y failed to close\n";
}
try {
z.close();
} catch(...) {
std::cerr << "z failed to close\n";
}
Of course you might want to common up that code a bit. Also, if you know everything close can throw, then you could have a better catch clause than (...).
This is possibly why the close() function of streams in the standard library doesn't throw an exception unless that behaviour has been enabled by the user setting the exception mask.

Related

Is logging in an exception constructor bad practice?

1.) What kind of exception logging is the better practice?
//1 xor //2
2.) Is this question language specific? (Most interested in c++)
To the code:
:: LOG is macro for singleton-logger
struct myExc : virtual std::runtime_error
{
myExc( std::string const&msg )
:runtime_error(msg)
{
LOG << msg; //1
}
};
void foo_throw()
{
throw myExc("");
}
/// some_where
...
try()
{
foo_throw();
}
catch( myExc const& e)
{
LOG << e.what(); //2
}
catch(...
The second variant is preferable, because some code further up the call stack could choose to catch the exception without outputting an error. In the first version, you output as soon as the exception is created, thus giving catching code less choice.
For example, you might do something like this:
try
{
foo_throw();
}
catch (myExc& e)
{
//do some recovery
}
If your exception constructor outputs something, you can't do anything about it when catching said exception.
The first one is probably 'too smart'. And do you sure about that the LOG << cannot throw exception? In second case you have more information and more possibilities to consider what happen if LOG << throws, especially you can do obligatory safe stuff before log.
And first case tried to does two things: inform about exception and log message. This is bad. In second case you only inform about exception and after that you handle it: do stuff and log.
Second case is example of separation of responsibility where one class does one task.
Also yours exception class is free from dependency of logger which is also good stuff.

C++ catching exception in constructor

How can I protect myself from using object which isn't fully created when using exceptions?
Should I catch in constructor ? Or maybe it's bad practice ? If I'll catch in constructor object will be created.
#include <stdio.h>
class A
{
public:
A()
{
try {
throw "Something bad happened...";
}
catch(const char* e) {
printf("Handled exception: %s\n", s);
}
// code continues here so our bad/broken object is created then?
}
~A()
{
printf("A:~A()");
}
void Method()
{ // do something
}
};
void main()
{
A object; // constructor will throw... and catch, code continues after catch so basically we've got
// broken object.
//And the question here:
//
//* is it possible to check if this object exists without catching it from main?
// &object still gives me an address of this broken object so it's created but how can I protect myself
// from using this broken object without writing try/catch and using error codes?
object.Method(); // something really bad. (aborting the program)
};
The language itself has no concept of an object being "invalid" in any detectable way.
If the exception indicates that a valid object can't be created, then it shouldn't be handled within the constructor; either rethrow it, or don't catch it in the first place. Then the program will leave the scope of the object being created, and it won't be possible to incorrectly access it.
If that isn't an option for some reason, then you'll need your own way to mark the object as "invalid"; perhaps set a boolean member variable at the end of the constructor to indicate success. This is flaky and error-prone, so don't do it unless you've got a very good reason.
If the object is in an invalid state when a certain exception is thrown, then I would let the exception unwind the call stack so the caller can be notified (and therefore react) to such things.
However, if the exception is one you can recover from, it may be worth trying to do so depend on your application. Make sure you use something like a logger or even simply stderr to indicate this is happening though.
I am going to suggest a first iteration of doing something more like this:
try {
throw "Something bad happened...";
}
catch(const std::exception e) {
cerr << e.what () << endl ; // Better off in the main
throw ;
}
Two things here:
Unless your exception handler handles the exception, it should throw.
Always use exception classes based upon std::exception to that you can always find out what the problem was as shown above.

std::shared_ptr: Custom deleter not being invoked

I'm working through C++ Primer, 5th edition, and the author has presented an example to do with using shared_ptrs to manage resources from older libraries that could leak memory, to prevent them from doing so. I decided to create a test to see how it works, but my custom deleter doesn't get called after the exception is thrown and (deliberately) not caught:
#include <iostream>
#include <memory>
#include <string>
struct Connection {};
Connection* Connect(std::string host)
{
std::cout << "Connecting to " << host << std::endl;
return new Connection;
}
void Disconnect(Connection* connection)
{
std::cout << "Disconnected" << std::endl;
delete connection;
}
void EndConnection(Connection* connection)
{
std::cerr << "Calling disconnect." << std::endl << std::flush;
Disconnect(connection);
}
void AttemptLeak()
{
Connection* c = Connect("www.google.co.uk");
std::shared_ptr<Connection> connection(c, EndConnection);
// Intentionally let the exception bubble up.
throw;
}
int main()
{
AttemptLeak();
return 0;
}
It produces the following output:
Connecting to www.google.co.uk
My understanding is that when a function is exited, whether that's exiting normally or because of an exception, the local variables will all be destroyed. In this case, that should mean connection being destroyed when AttemptLeaks() exits, invoking its destructor, which should then call EndConnection(). Notice also that I'm using, and flushing, cerr, but that also didn't give any output.
Is there something wrong with my example, or my understanding?
Edit: While I already have the answer to this question, for anyone else that stumbles upon this in the future, my problem was with my understanding of how throw works. Although the answers below correctly state how to use it, I think it's best to explicitly make it clear that I was (incorrectly) trying to use it to 'generate' an unhandled exception, to test my code above.
Bare throw is intended for use inside catch blocks to rethrow a caught exception. If you use it outside a catch block, terminate() will be called and your program ends at once. See what does "throw;" outside a catch block do?
If you delete the throw-statement the shared_ptr connection will go out of scope and should call the deleter. If you have any doubts about the exception-safety of using a shared_ptr (I don't ;), you can explicitly throw an exception here by changing throw to throw 1.
The throw expression without an operand is intended for rethrowing the exception being currently handled. If no exception is being handled then std::terminate is called. In this situation stack unwinding does not take place, which is why the deleter is never being called. Change your code to the folowing:
void AttemptLeak()
{
Connection* c = Connect("www.google.co.uk");
std::shared_ptr<Connection> connection(c, EndConnection);
// Intentionally let the exception bubble up.
throw 42; // or preferably something defined in <stdexcept>
}
int main()
{
try {
AttemptLeak();
} catch(...) {
}
return 0;
}
Now the deleter will be called when the shared_ptr goes out of scope.

intermixing c++ exception handling and SEH (windows)

I have a function in which I call getaddrinfo() to get an sockaddr* which targets memory is allocated by the system.
As many may know, you need to call freeaddrinfo() to free the memory allocated by getaddrinfo().
Now, in my function, there are a few places, where I may throw an exception, because some function failed.
My first solution was to incorporate the freeaddrinfo() into every if-block.
But that did look ugly for me, because I would have had to call it anyways before my function returns, so I came up with SEH`s try-finally...
But the problem I encountered is, that it is not allowed to code the throw-statements into the __try-block
Then, I read on the msdn and tried to swap the throw-statements into the helper function called from within the __try-block... and voila, the compiler didnĀ“t moan it anymore...
Why is that? And is this safe? This does not make sense to me :/
Code:
void function()
{
//...
addrinfo* pFinal;
__try
{
getaddrinfo(..., &pFinal);
//if(DoSomething1() == FAILED)
// throw(exception); //error C2712: Cannot use __try in functions that require object unwinding
//but this works
Helper();
//...
}
__finally
{
freeaddrinfo();
}
}
void Helper()
{
throw(Exception);
}
EDIT:
tried the following and it works with throwing an integer, but does not when i use a class as an exception:
class X
{
public:
X(){};
~X(){};
};
void Helper()
{
throw(X());
}
void base()
{
__try
{
std::cout << "entering __try\n";
Helper();
std::cout << "leaving __try\n";
}
__finally
{
std::cout << "in __finally\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
base();
}
catch(int& X)
{
std::cout << "caught a X" << std::endl;
}
std::cin.get();
return 0;
}
Why? :/
You can't mix the two exception types. Under the covers, C++ exceptions use SEH and your SEH exception handler could mess up the exception propogation logic. As a result, the C++ compiler won't allow you to mix them.
PS: Structured Exception Handling is almost always a VERY bad idea. Internally Microsoft has banned the use of SEH except in very limited circumstances. Any component that does use structured exception handling is automatically subject to intense code reviews (we have tools that scan code looking for its use to ensure that no cases are missed).
The problem with SEH is that it's extremely easy to accidentally introduce security vulnerabilities when using SEH.
You could wrap the addrinfo in a class that calls getaddrinfo in the constructor and freeaddrinfo in its destructor.
That way it will always be freed, whether there is an exception thrown or not.
catch(int& X)
{
std::cout << "caught a X" << std::endl;
}
That doesn't catch an X, it catches an int&. Since there is no matching catch block, the exception is uncaught, stack unwinding doesn't occur, and __finally handlers don't run.
You can put catch (...) in your thread entrypoint (which is main() for the primary thread) in order to make sure that stack unwinding occurs, although some exceptions are unrecoverable, that's never true of a C++ exception.

Reasons for stack unwinding fail

I was debugging an application and encountered following code:
int Func()
{
try
{
CSingleLock aLock(&m_CriticalSection, TRUE);
{
//user code
}
}
catch(...)
{
//exception handling
}
return -1;
}
m_CriticalSection is CCricialSection.
I found that user code throws an exception such that m_CriticalSection is not released at all. That means due to some reasons stack is corrupted and hence unwinding failed.
My question is:
1) In what different scenarios stack unwinding can fail ?
2) what different possibility of exception can be thrown such that stack unwinding fails.
3) Can I solve this problem by putting CSingleLock outside of try block ?
Thanks,
Are you getting an abnormal program termination?
I believe your CCriticalSection object will be released CSingleLock's destructor. The destructor will get called always since this is an object on the stack. When the usercode throws, all stacks between the throw and the catch in your function will be unwound.
However, chances are that some other object in your user code or even the CSingleLock destructor has thrown another exception in the meantime. In this case the m_CriticalSection object will not get released properly and std::terminate is called and your program dies.
Here's some sample to demonstrate. Note: I am using a std::terminate handler function to notify me of the state. You can also use the std::uncaught_exception to see if there are any uncaught exceptions. There is a nice discussion and sample code on this here.
struct S {
S() { std::cout << __FUNCTION__ << std::endl; }
~S() { throw __FUNCTION__; std::cout << __FUNCTION__ << std::endl; }
};
void func() {
try {
S s;
{
throw 42;
}
} catch(int e) {
std::cout << "Exception: " << e << std::endl;
}
}
void rip() {
std::cout << " help me, O mighty Lord!\n"; // pray
}
int main() {
std::set_terminate(rip);
try {
func();
}
catch(char *se) {
std::cout << "Exception: " << se << std::endl;
}
}
Read this FAQ for clarity.
Can I solve this problem by putting CSingleLock outside of try block ?
Hard to say without having a look at the stack and error(s)/crashes. Why don't you give it a try. It may also introduce a subtle bug by hiding the real problem.
Let me start by saying that I don't know what CSingleLock and CCriticalSection do.
What I do know is that an exception thrown in your "user code" section should unwind the stack and destroy any variables that were created within the try { } block.
To my eyes, I would expect your aLock variable to be destroyed by an exception, but not m_CriticalSection. You are passing a pointer to m_CriticalSection to the aLock variable, but the m_CriticalSection object already exists, and was created elsewhere.
are you sure that lifetime of your m_CriticalSection is longer that CSingleLock?
maybe someone corrupt your stack?
3) Can I solve this problem by putting CSingleLock outside of try block ?
in this case - yes. But remember, it is not good thing for performance to put large block in mutex.
btw, catch(...) is not good practice in general. in Win32 it (catch(...)) catching SEH exceptions too, not only c++ exception. maybe you have core in this function and catch it with catch(...).
My question is:
1) In what different scenarios stack unwinding can fail ?
If exit() terminate() abort() or unexpected() are called.
With the exception of a direct calls what situations are any of these likely to happen:
An unhandeled exception is thrown. (Does not apply here)
throw an exception from a destructor while another exception is popogating
2) what different possibility of exception can be thrown such that stack unwinding fails.
Exception thrown from constructor of throw expression
Exception thrown from destructor while exception propogating.
Exception thrown that is never caught (implementatin defined if this actually unwinds stack).
Exception thrown that is not specified in exception specification.
Exception thrown across a C ABI.
Exception thrown inside a thread that is not caught (Implementation defined what happens)
3) Can I solve this problem by putting CSingleLock outside of try block ?
No. All of the above cause the application to terminate without further unwinding of the stack.