Is logging in an exception constructor bad practice? - c++

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.

Related

Catch(...) with unknown object - how do I identify what was thrown?

I have a library I use that throws something, but I don't know how to identify what was being thrown.
Sample code to reproduce this:
int main()
{
char* memoryOutOfBounds;
unsigned __int64 bigNumber = -1;
try {
throw std::string("Test");
memoryOutOfBounds = new char[bigNumber];
}
catch (const std::bad_alloc& ex)
{
printf("Exception: %s\n", ex.what());
}
catch (...)
{
printf("Unknown.\n");
}
return 0;
}
The new char[bigNumber] will throw a std::bad_alloc, which is derived from std::exception and will enter the first branch. The other one, throw std::string will enter the second branch. How can I check the object that was thrown? I tried with a catch(void*) in the hopes to catch any object in memory, but that did not happen, so how can I find out what was thrown and from there debug what may have caused this?
catch (...) {}
means: Catch absolute everything that was thrown and drop it. This is only meant as a safeguard, so no exceptions fly out of the window and bring down the whole house. (Aka: Application Termination by Unhandled Exception")
There is no way to tell what was thrown in here.
But as you actually know that an std::string can be thrown, you can catch it in a
catch (const std::string& s) {}
block. You do need to know what (type) was thrown whenever you want to catch exceptions.
However, most libraries which add their own types for exceptions will have them inherit from std::exception. Therefore a
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
block should get them.
If they do not inherit from std::exception and/or block the what() method, it is a stupid way to make the usage of their library extra difficult.
However, somewhere in the documentation of the library the exception throwing behaviour should be explained.
Edit : I think that Point 1. under "How should I design my exception classes" on the Boost Error Handling document is something every library developer should keep in mind. And hopefully the developers of your library did keep that principle in mind. ;-)
There really is no standard C++ way to query any information about the exception that is being thrown. Which is unfortunate, because the runtime has that information in order to match catch blocks. But there is just no access to that information in user code.
If it's purely for research purposes, like just finding out what the type is because the library you're using lacks documentation, you could use std::current_exception() to get a std::exception_ptr object that stores (or references) the thrown exception internally. This type is implementation-defined, but your debugger might happen to provide you with enough information.
#include <exception>
void foo()
{
try
{
function_that_throws();
}
catch(...)
{
std::exception_ptr p = std::current_exception();
// break here and inspect 'p' with a debugger
}
}
This stackoverflow post would be helpful-
C++ get description of an exception caught in catch(...) block
Since C++11 you can capture the current exception with a pointer:
std::exception_ptr p; // default initialization is to nullptr
try {
throw std::string("Test");
}
catch(...)
{
p = std::current_exception();
}

Is it important that what() does not throw (exception classes)?

An exercise from C++ Primer asks
Why is it important that the what function [of exception classes] doesn’t throw?
Since there is no way to check my answer I was hoping to get an opinion. I thought possibly that it is an error (maybe terminate would've been called) to throw another exception during a catch clause (other than a rethrow throw;) while the current exception object is still being handled. It seems that is not the case though and it is completely okay to throw out of catch clauses:
#include <iostream>
using namespace std;
int main(){
try{
try{
throw exception();
} catch(exception err){ throw exception();}
} catch(exception err){ cout << "caught"} //compiles and runs fine, outputs "caught"
}
So program terminations are not a worry. It seems then, any problem that arises from what() throwing should, at the very least, be rectifiable by the user if they were so inclined.
Maybe then, the importance might be that while handling an error we do not want further unexpected errors to occur? Throws inside catch clauses are mainly intended for sending the exception object further up the call chain. A user may receive an error from deep in his program and does not want to worry that the error caught has to be associated with its own try block. Or maybe what() having its own throw may also lead to recursive effects (e.g. what() throws an exception, then we catch this exception and call what() but this then throws, and so on) meaning it might become impossible to handle any errors? How drastic can it be for what() to potentially throw?
I think there's nothing unclear - it's just as you described. If .what() method of an exception class throws an error, the whole catch effort was wasted:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Ooops, instead of false,
//we get another exception totally unrelated to original error
someLogClassOrWhatever.save(e.what());
return false;
}
return true;
And Imagine the crazy code if you were expected to deal with what()'s exceptions:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Not very fun
try {
someLogClassOrWhatever.save(e.what());
}
catch(...) {
alsoWhatHasFailedThatIsReallyGreat();
}
return false;
}
I think there's nothing more in that, probably the question is so simple it seems there must be some catch hiding in it. I think it's not the case.
std::exception::what() is noexcept. Consequently, if it throws, std::terminate is called. Yes, this is important.
Image a very curious coder with a slight tendency towards being a control freak (I know a couple of them myself), he really wants to know what is going wrong in his program and logs all errors with ex.what(). So he codes
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
He is pretty pleased with the world in general and with himself in particular. But now it crosses his mind, that e.what() could throw an exception as well. So he is codes:
try{
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
}
catch(std::exception &e) {
std::cout<<e.what()
}
A minute later he notices, that there is again an uncaught exception possible! Remember, he is a control freak, so he is going to write another try-catch block and than another and another
So you can bet any money, his project will be late - how could you do something like this to my friend? So please make sure e.what() doesn't throw:)
I guess it is the reason behind what being noexcept.

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.

Catching and handling all exceptions in my own class

Hello to all and sorry for my english!
How can I do the title above?
For example, I have a class contains a some functions that can throw exceptions:
class cl {
public:
void f1();
void f2();
};
void cl::f1()
{
// throw exception
}
void cl::f2()
{
// throw exception
}
I need to handle them.
Are there any other method to handle exceptions (that throws in my class) in one place of the code except code like this:
void cl::f1()
{
try
{
// throw exception
}
catch (...)
{
// handling
}
}
void cl::f1()
{
try
{
// throw exception
}
catch (...)
{
// handling
}
}
or this:
int main()
{
cl c;
try
{
f1();
f2();
}
catch(...)
{
// handling
}
}
?
Thanks in advance!
Are there any other method to handle exceptions (that throws in my
class) in one place of the code except code like this:
In my opinion you would typically only handle an exception when:
You can remedy it i.e do something about it e.g allow the user to select a different file.
You can add additional information.
For the latter case, it would mean throwing a new exception (possible of different type) from the handler.
If neither of the above hold, let it propagate to a level where it can be handled. In your case, I would not have a try/catch within f1 and f2, but only at the callsite (in main).
You might ask whether one cannot(should not) do certain cleanup work in the catch handler. I personally have never found this to be necessary if/when one uses the stack/scope to clean up see RAII. I/we usually have one catch handler per thread at the highest level, and this simply performs logging. We catch (and use exceptions) for runtime errors mostly. For logic errors we use assert (even in release mode), but this can be (and have been) debated often.

How to handle a file destructor throwing an exception?

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.