Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Eg
class MyThrowingClass {
MyThrowingClass() {throw exception();}
doSomethingImportant() {
//...
}
};
int main() {
//Need to catch the exception:
try {
MyThrowingClass myObj;
} catch() {
//actually handle the error
//...
}
//Also need to use myObj later on
myObj.doSomethingImportant();//but we can't use it here because it was scoped to the try block...
}
If I have myObj encased in a try then nothing outside the scope of the try can see it, but I don't want to have everything else inside there because then the code becomes 30 levels of nested try blocks, which is what the exception handling is supposed to remove with using the alternative of init function error codes.
I can't handle the exception inside the constructor as the reaction to the exception depends on the context of the use of MyThrowingClass.
Obviously the problem could be circumvented by having a
MyThrowingClass* pMyObj;
and then being able to wrapper the
pMyObj = new MyThrowingClass();
but surely this should be achievable with a stack allocated object too?
Is the only solution to do something like
MyThrowingClass myObj;
try {
myObj.init();
} catch(...) {
//...
}
at which point we're back to basically as bad as error codes and having an uninitialised or partially initialised object.
Note that this is not intended to be a global object, I want to have something that will be instantiated in many places.
Is it really the ideal solution to have a try block that wraps the entire scope (here everything that would be inside main) and catches that handle every possible exception at the end of that one try block as opposed to being able to handle exceptions vaguely near to their site?
int main() {
try {
//absoultely everything
}
catch (exceptionTypeA &a) {
//...
}
catch exceptionTypeB &b) {
}
}
how do I make the object accessible from outside the try block where it is constructed?
If construction fails, then the object doesn't exist; so there's nothing to access.
surely this should be achievable with a stack allocated object too?
Automatic (i.e. stack-allocated) objects are only initialised once, so even if you handle the exception, there's no way to go back and try to re-initialise it. If you do want to be able to retry, then you'll have to use something more complicated, like the dynamic allocation or two-stage initialisation you propose. Another alternative is something boost::optional (or, from next year, std::optional), which allows you to create and destroy objects at will within a lump of automatic storage.
Is it really the ideal solution to have a try block that wraps the entire scope?
In the typical case, where exceptions aren't handled locally and initialisation failure indicates an unrecoverable error, yes. In your special case, where you can handle it locally and recover, no.
try is designed to scope objects that can throw for a reason. By working around it, you are circumventing that which it's trying to protect you from (using a poorly defined object.) Consider using a function to generate the object. By using a noexcept move constructor, you can guarantee that the move out of the object is safe:
class MyThrowingClass {
public:
MyThrowingClass() {
throw exception();
}
// throw() is *okay* if you don't have noexcept
MyThrowingClass(const MyThrowingClass && other) noexcept {
}
};
MyThrowingClass GetObj() {
try {
return std::move(MyThrowingClass());
} catch(...) {
// return some well defined default or terminate program
}
}
int main() {
MyThrowingClass myObj(std::move(GetObj()));
}
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Basically, you can't. As for wrapping ALL the code in a try block being a good or bad idea, that depends on the size of "all the code" - a dozen lines or so lines is no big deal.
Do you really want to call MyThrowingClass::doSomethingImportant() if the initialiser throws? Unless you somehow guarantee to fix the broken initialisation in the catch you're then calling methods on a partially initialised object.
Including the call to doSomethingImportant() in the same try block as the construction of the object would give you exactly what exceptions are designed to do: in the event of a problem skip past the following code (which is dependent on the preceding code) to an error handler.
Related
In my application, I have a Singleton that represents "the system". This object is created first and destroyed last and all other objects are supposed to be managed by it, which means, each object will be created directly or indirectly by this system object (in its run method) and all objects will (hopefully) be removed before the system gets unavailable.
The problem is that an optional access to the system object (via pointer) introduces lots of not-null checking code. I know that dereferencing a null pointer results in undefined behaviour. Is using the good old C-assert the best I can do?
// this is mostly pseudo-code, but should compile if
// there is an appropriate MySys header
#include "MySys.h"
class MySysImplementation: public MySys
{
public:
MySysImplementation();
void run();
// ...
};
/// pointing to system object during runtime
namespace {
MySys* g_sys = NULL;
}
MySys& MySys::Instance()
{
assert(g_sys);
return *g_sys;
}
int main()
{
{
MySysImplementation sys;
g_sys = &sys;
sys.run();
} // <---------- HERE all application-specific objects should be gone
g_sys = NULL; // in real code this RAII-ensured
}
The problem is that an optional system object introduces lots of not-null checking code.
Consider replacing it with a null object:
class MySys {
virtual void some_op() = 0;
// other operations here
};
class NullSystem: public MySys {
void some_op() {} // no-op implementations for all APIs
};
class YourSystem: public MySys {
void some_op() { /* your non-optional implementation here */ }
};
I know that dereferencing a null pointer results in undefined behaviour. Is using the good old C-assert the best I can do?
First, don't use a global for the instance and don't use a singleton access point (your MySys::Instance()). The singleton pattern is an anti-pattern (it shows mostly what not to do).
Consider instantiating an object in main and passing that around by reference (that is, use dependency injection instead of singletons):
class SomeClientClass
{
SomeClientClass(MySys const & system);
};
int main(int, char**)
{
auto system = std::make_unique<YourSystem>();
auto someClientCode = SomeClientClass(*system);
// ...
// example where you want a SomeClientClass instance without system:
auto client2 = SomeClientClass{ NullSystem{} };
}
While asserts can be removed in a release mode you may be better of by throwing an exception instead.
Your program may crash by just using the null pointer without exception but this is undefined behavior and can have all possible side effects.
An exception also has the advantages that the objects you created get cleaned up (stack unwind) and you also have the chance to catch the exception and deal with it if you have a part of your code where you are able to properly deal with this.
You can throw whatever you like, but it is recommended to throw anything derived from std::exception. std::runtime_error seems good here. Or derive something yourself.
One thing to note though:
Because you are working on a global object (singletons are also global) you should avoid using the singleton in a destructor. When an exception gets thrown and you are "stack-unwinding" and one of those objects destructors would throw a second exception the program will immediately call std::terminate. If you terminate anyway this might not be a problem, but if you want to catch the exception somewhere or you rely on stack-unwinding this may lead to issues.
You might simply do something like:
MySys& MySys::Instance()
{
static MySysImplementation instance;
return instance;
}
Is using the good old C-assert the best I can do?
It's one option. Whether it's best depends on what you need the program to do when a null pointer is used.
There are two aspects of assert:
It is disabled conditionally, depending on the NDEBUG macro - which is typically enabled in a release build. If you would like to detect the null pointer unconditionally, an if statement is a better alternative.
It calls std::abort which terminates the process. If the situation could be resolved in a more graceful manner, then assertion isn't the best option for you. Instead, you could throw an exception, and catch it higher in the call stack where it can be handled.
If you cannot handle the exception meaningfully anyway, and if you prefer to avoid the runtime cost of the check in the release build, then assertion is indeed best that you can do.
However if possible, you might alternatively guarantee that the object does necessarily exist by using a static instance. Consider following:
MySys& MySys::Instance()
{
static MySysImplementation sys;
return sys;
}
This sys is guaranteed to exist before and after any object, that calls MySys::Instance within its constructor - or whose construction is otherwise guaranteed to be after the MySysImplementation has been constructed.
So the way to nest exceptions in C++ using std::nested_exception is:
void foo() {
try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
}
But this technique uses explicit try/catch blocks at every level where one wishes to nest exceptions, which is ugly to say the least.
RAII, which Jon Kalb expands as "responsibility acquisition is initialization", is a much cleaner way to deal with exceptions instead of using explicit try/catch blocks. With RAII, explicit try/catch blocks are largely only used to ultimately handle an exception, e.g. in order to display an error message to the user.
Looking at the above code, it seems to me that entering foo() can be viewed as entailing a responsibility to report any exceptions as std::runtime_error("foo failed") and nest the details inside a nested_exception. If we can use RAII to acquire this responsibility the code looks much cleaner:
void foo() {
Throw_with_nested on_error("foo failed");
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
Is there any way to use RAII syntax here to replace explicit try/catch blocks?
To do this we need a type that, when its destructor is called, checks to see if the destructor call is due to an exception, nests that exception if so, and throws the new, nested exception so that unwinding continues normally. That might look like:
struct Throw_with_nested {
const char *msg;
Throw_with_nested(const char *error_message) : msg(error_message) {}
~Throw_with_nested() {
if (std::uncaught_exception()) {
std::throw_with_nested(std::runtime_error(msg));
}
}
};
However std::throw_with_nested() requires a 'currently handled exception' to be active, which means it doesn't work except inside the context of a catch block. So we'd need something like:
~Throw_with_nested() {
if (std::uncaught_exception()) {
try {
rethrow_uncaught_exception();
}
catch(...) {
std::throw_with_nested(std::runtime_error(msg));
}
}
}
Unfortunately as far as I'm aware, there's nothing like rethrow_uncaught_excpetion() defined in C++.
In the absence of a method to catch (and consume) the uncaught exception in the destructor, there is no way to rethrow an exception, nested or not, in the context of the destructor without std::terminate being called (when the exception is thrown in the context of exception handling).
std::current_exception (combined with std::rethrow_exception) will only return a pointer to a currently handled exception. This precludes its use from this scenario as the exception in this case is explicitly unhandled.
Given the above, the only answer to give is from an aesthetic perspective. Function level try blocks make this look slightly less ugly. (adjust for your style preference):
void foo() try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
It's impossible with RAII
Considering the simple rule
Destructors must never throw.
it is impossible with RAII to implement the thing you want. The rule has one simple reason: If a destructor throws an exception during stack unwinding due to an exception in flight, then terminate() is called and your application will be dead.
An alternative
In C++11 you can work with lambdas which can make life a little easier. You can write
void foo()
{
giveErrorContextOnFailure( "foo failed", [&]
{
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
} );
}
if you implement the function giveErrorContextOnFailure in the following way:
template <typename F>
auto giveErrorContextOnFailure( const char * msg, F && f ) -> decltype(f())
{
try { return f(); }
catch { std::throw_with_nested(std::runtime_error(msg)); }
}
This has several advantages:
You encapsulate how the error is nested.
Changing the way errors are nested can be changed for the whole program, if this technique is followed strictly program wide.
The error message can be written before the code just as in RAII. This technique can be used for nested scopes as well.
There's less code repetition: You don't have to write try, catch, std::throw_with_nested and std::runtime_error. This makes your code more easily maintainable. If you want to change the behavior of your program you need to change your code in one place only.
The return type will be deduced automatically. So if your function foo() should return something, then you just add return before giveErrorContextOnFailure in your function foo().
In release mode there will typically be no performance panelty compared to the try-catch-way of doing things, since templates are inlined by default.
One more interesting rule to follow:
Do not use std::uncaught_exception().
There's a nice article about this topic by Herb Sutter which explains this rule perfectly. In short: If you have a function f() which is called from within a destructor during stack unwinding looking like this
void f()
{
RAII r;
bla();
}
where the destructor of RAII looks like
RAII::~RAII()
{
if ( std::uncaught_exception() )
{
// ...
}
else
{
// ...
}
}
then the first branch in the destructor will always be taken, since in the outer destructor during stack unwinding std::uncaught_exception() will always return true, even inside functions called from that destructor including the destructor of RAII.
I know that having global variables is not appreciated. But in the book, The C++ programming language, by Bjarne Stroustrup, Author says that " The only way to gain control in case of throw from an initializer of a non local static object is set_unexpected() ". How is it done?
I posted the question in some other forums and got some answers.
First one was to declare a pointer rather than having an object and to initialize it in main()
Second one was to derive the class (whose constructor throws the exception ) from another class which performs set_terminate so as to set a meaningful handler. The second one seems to work fine in codeblocks ide.
The code I used to test check it is:
void f() //Unexpected exception handler
{
cout<<"Terminate called "<<endl;
exit (0);
}
class A //Base class that performs set_unexpected
{
terminate_handler h;
public:
A()
{
h=set_terminate(f);
}
~A()
{
set_terminate(h);
}
};
class B:public A //Derived class that throws unexpected_exception
{
public:
B()
{
throw 1;
}
};
B b;
int main()
{
}
The program displays the message: "Terminate called" and exits.
try/catch block are within or along with function scope. Thus global objects cannot reside within try/catch scope, so you can never catch those exceptions.
You can explore the special try/catch syntax:
class Test {
public:
Test ()
try { throw 0; }
catch(...) {}
};
This provides some relief in handling such exceptions. Here is one thread discussing the same.
However, you have to provide such syntax for every class for which you declare global objects
You might be wondering that what's the difference if you put try/catch inside the constructor itself? Well if a global object fails to initialize then the internal try/catch will silently absorb it, which is bad.
But the above syntax will give you a chance for error diagnosis and then again rethrow the exception which will terminate the program.
See this thread for more details.
On the other hand, std::unexpected() is called when there is no appropriate catch() for a thrown exception. This function is standard, but you can configure your own by using std::set_unexpected().
It's very easy to miss the point with error handling in C++, with exceptions, terminate, abort, and so on. The premise that regular code really fears to brake is that destructors will clean up everything constructed so far. So stack unwinding should be the focus, not the means you use for error handling, be it exceptions or something else.
To end the program in a catch in main(), usually you just return an error, or exit(EXIT_FAILURE), so after the stack unwinding you already performed, static duration variables are also destroyed normally.
With global variables that are initialized before main(), that's often all you need. You can preserve destructors functionality simply by using exit instead of throw in their constructors. Other global variables constructed so far are destroyed before the program ends, unlike with throw in a default setup. exit does not unwind the stack, but at this moment there are no destructors to be called by unwinding (except as edited below).
This might be a simpler solution for later readers with the problem in the question title.
EDIT: Besides automatic duration variables, stack unwinding also destroys completed bases and members of a class that throws on construction, which the exit solution does not cover. If you have a global with subobjects that need destruction, you still have to wrap its constructor in a try/catch, or manage its constructor failure manually. The catch in this case needs to call exit for other already constructed globals to be destroyed.
I have a case in which I have to read an input file in the C'tor, but sometimes this file doesn't exist.
This object is usually held statically, so its C'tor is called while loading the dll.
I can't catch the exception I throw if the file doesn't exist because it's too early, and my executable crashes in an ugly way.
I know it's bad practice to throw exceptions out of a C'tor, but I can't go on if the file doesn't exist, so I have to.
Is there a way to catch the exception while loading the dll, and if not, is there any better solution for this scenario?
Thanks,
Gal
I assume the static object has the file scope (it is outside any function/class definition). You may consider moving it to an accessor function and accessing it only via that function, like this:
class Object;
Object& getObject()
{
static Object object;
return object;
}
The static instance of Object will be initialized upon the first calling of the getObject() method. If the Object's constructor throws, you can easily catch the exception. Just you need to remember wrapping every call of getObject() into a try/catch block (or suffer from the exception bubbling up the stack chain); that may be a bit inconvenient, but on the other hand you may decide to wrap just the logically "first" call, if you know which one it is in the program logic flow.
Throwing exceptions out of a constructor is not necessarily a bad practice. In fact, RAII usually requires you to do this sort of things, because objects have an internal invariant that must be satisfied, and if the constructor can't initialize the object and leave it in a valid state, then it's the only way to go.
Throwing exceptions from a destructor, on the other hand, is a bad practice (and also a dangerous one). But throwing them from a constructor should be OK.
If you can use c++11 then there is a lambda and unique_ptr<> solution to this:
// In some_file.hpp
#pragma once
#include <memory>
#include <stdexcept>
class CtorThrows {
public:
CtorThrows (int value) {
if (value < 10) {
throw std::runtime_error("oops!");
}
}
};
class ClassWithStatic {
public:
private:
static std::unique_ptr<CtorThrows> bad_member_; // <-- static member
};
and then
// In some_file.cpp
#include "some_file.hpp"
// Create a lambda function to initialize the static member variable.
std::unique_ptr<CtorThrows> ClassWithStatic::bad_member_ = []() {
try {
int value = 5; // in this case, it is a bad value
// This only returns successfully if bad_value DOESN'T cause
// the ctor to throw and exception.
return std::make_unique<CtorThrows>(value);
} catch (std::runtime_error &e) {
std::cerr << "OOPs! Here's a nice error message" << std::endl;
exit(1);
}
return std::unique_ptr<CtorThrows>(nullptr);
}();
Using a unique_ptr lets you do this even with classes with that have a deleted or private copy constructor and copy assignment operator.
Redesign the object in such a way that it opens the file later - for example when the data from the file is requested the first time.
Alternatively replase the static object with a static pointer and call new when needed. It's better to use a smart pointer like auto_ptr.
How about separating reading the input file from the Constructor? You could have a separate Init() Method that must be called after constructing the object but before the object is actually ready to use.
You're right that you can't catch exeptions that happen during the initialization of static objects.
Since you're writing a DLL: Each DLL can have an entry-point, and inside this entry point exception handling works. (It's the same as main in your main-program). I'd remove the static instances of your classes, replace them with pointers and initialize these pointers inside dllmain.
That'll solve your problems once for all.
Btw - the DLL entrypoint gets called on load, unload and other events such as process attach/detach ect. Be sure you use the correct place to initialize your classes.
One way may be to "design" this to make the calling code (i.e. the code outside the dll) responsible for making sure all dependencies of the dll is in place. A function in the calling code that makes sure the dll's dependencies, in this case the file, is in place and is loadable before loading the library. If not, it can gracefully exit.
Is this a good way to implement a Finally-like behavior in standard C++?
(Without special pointers)
class Exception : public Exception
{ public: virtual bool isException() { return true; } };
class NoException : public Exception
{ public: bool isException() { return false; } };
Object *myObject = 0;
try
{
// OBJECT CREATION AND PROCESSING
try
{
myObject = new Object();
// Do something with myObject.
}
// EXCEPTION HANDLING
catch (Exception &e)
{
// When there is an excepion, handle or throw,
// else NoException will be thrown.
}
throw NoException();
}
// CLEAN UP
catch (Exception &e)
{
delete myObject;
if (e.isException()) throw e;
}
No exception thrown by object -> NoException -> Object cleaned up
Exception thrown by object -> Handled -> NoException -> Object cleaned up
Exception thrown by object -> Thrown -> Exception -> Object cleaned up -> Thrown
The standard answer is to use some variant of resource-allocation-is-initialization abbreviated RAII. Basically you construct a variable that has the same scope as the block that would be inside the block before the finally, then do the work in the finally block inside the objects destructor.
try {
// Some work
}
finally {
// Cleanup code
}
becomes
class Cleanup
{
public:
~Cleanup()
{
// Cleanup code
}
}
Cleanup cleanupObj;
// Some work.
This looks terribly inconvenient, but usually there's a pre-existing object that will do the clean up for you. In your case, it looks like you want to destruct the object in the finally block, which means a smart or unique pointer will do what you want:
std::unique_ptr<Object> obj(new Object());
or modern C++
auto obj = std::make_unique<Object>();
No matter which exceptions are thrown, the object will be destructed. Getting back to RAII, in this case the resource allocation is allocating the memory for the Object and constructing it and the initialization is the initialization of the unique_ptr.
No. The Standard way to build a finally like way is to separate the concerns (http://en.wikipedia.org/wiki/Separation_of_concerns) and make objects that are used within the try block automatically release resources in their destructor (called "Scope Bound Resource Management"). Since destructors run deterministically, unlike in Java, you can rely on them to clean up safely. This way the objects that aquired the resource will also clean up the resource.
One way that is special is dynamic memory allocation. Since you are the one aquiring the resource, you have to clean up again. Here, smart pointers can be used.
try {
// auto_ptr will release the memory safely upon an exception or normal
// flow out of the block. Notice we use the "const auto_ptr idiom".
// http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
std::auto_ptr<A> const aptr(new A);
}
// catch...
If for some strange reason you don't have access to the standard libraries, then it's very easy to implement as much as you need of a smart pointer type to handle the resource. It may look a little verbose, but it's less code than those nested try/catch blocks, and you only have to define this template once ever, instead of once per resource that needs management:
template<typename T>
struct MyDeletable {
explicit MyDeletable(T *ptr) : ptr_(ptr) { }
~MyDeleteable() { delete ptr_; }
private:
T *ptr_;
MyDeletable(const MyDeletable &);
MyDeletable &operator=(const MyDeletable &);
};
void myfunction() {
// it's generally recommended that these two be done on one line.
// But it's possible to overdo that, and accidentally write
// exception-unsafe code if there are multiple parameters involved.
// So by all means make it a one-liner, but never forget that there are
// two distinct steps, and the second one must be nothrow.
Object *myObject = new Object();
MyDeletable<Object> deleter(myObject);
// do something with my object
return;
}
Of course, if you do this and then use RAII in the rest of your code, you'll eventually end up needing all the features of the standard and boost smart pointer types. But this is a start, and does what I think you want.
The try ... catch approach probably won't work well in the face of maintenance programming. The CLEAN UP block isn't guaranteed to be executed: for example if the "do something" code returns early, or somehow throws something which is not an Exception. On the other hand, the destructor of "deleter" in my code is guaranteed to be executed in both those cases (although not if the program terminates).
My advice is: don't try to emulate the behaviour of a try-finally clause in C++. Just use RAII instead. You'll live happier.
Assuming you are looking to delete the pointer myObject and avoid memory leaks, your code can still fail to do this if there is a "return" statement in the code where you say // Do something with myObject. (I am assuming real code would be here)
RAII techniques have the relevant action that is equivalent to a "finally" block, in a particular object's destructor:
class ResourceNeedingCleanup
{
private:
void cleanup(); // action to run at end
public:
ResourceNeedingCleanup( /*args here*/) {}
~ResourceNeedingCleanup() { cleanup(); }
void MethodThatMightThrowException();
};
typedef boost::shared_ptr<ResourceNeedingCleanup> ResourceNeedingCleanupPtr;
// ref-counted smart pointer
class SomeObjectThatMightKeepReferencesToResources
{
ResourceNeedingCleanupPtr pR;
void maybeSaveACopy(ResourceNeedingCleanupPtr& p)
{
if ( /* some condition is met */ )
pR = p;
}
};
// somewhere else in the code:
void MyFunction(SomeObjectThatMightKeepReferencesToResources& O)
{
ResourceNeedingCleanup R1( /*parameters*/) ;
shared_ptr<ResourceNeedingCleanup> pR2 =
new ResourceNeedingCleanup( /*parameters*/ );
try
{
R1.MethodThatMightThrowException();
pR2->MethodThatMightThrowException();
O->maybeSaveACopy(pR2);
}
catch ( /* something */ )
{
/* something */
}
// when we exit this block, R1 goes out of scope and executes its destructor
// which calls cleanup() whether or not an exception is thrown.
// pR2 goes out of scope. This is a shared reference-counted pointer.
// If O does not save a copy of pR2, then pR2 will be deleted automatically
// at this point. Otherwise, pR2 will be deleted automatically whenever
// O's destructor is called or O releases its ownership of pR2 and the
// reference count goes to zero.
}
I think I have the semantics correct; I haven't used shared_ptr much myself, but I prefer it to auto_ptr<> -- a pointer to an object can only be "owned" by one auto_ptr<>. I've used COM's CComPtr and a variant of it that I've written myself for "regular" (non-COM) objects that is similar to shared_ptr<> but has Attach() and Detach() for transfer of pointers from one smart pointer to another.
To directly answer your question, no.
It's a clever way to implement that functionality, but it is not reliable. One way that will fail you is if your "do something" code throws an exception that is not derived from Exception. In that case, you will never delete myObject.
There's a more important issue at hand here, and that's the methodologies adopted by programmers of any particular language. The reason you're hearing about RAII is because programmers with much more experience than you or I have found that in the domain of C++ programming, that methodology is reliable. You can rely on other programmers using it and other programmers will want to rely on you using it.