C++ classes provide RAII idiom. Therefore you don't have to care about exceptions:
void function()
{
// The memory will be freed automatically on function exit
std::vector<int> vector(1000);
// Do some work
}
But if you have (for some reasons) to use some pure C API, you have either to create C++ wrappers around it or to use try/catch blocks
void function()
{
int *arr = (int*)malloc(1000*sizeof(int));
if (!arr) { throw "cannot malloc"; }
try
{
// Do some work
}
catch (...)
{
free(arr); // Free memory in case of exception
throw; // Rethrow the exception
}
// Free memory in case of success
free(arr);
}
Even if you use C++ classes with RAII idiom, sometimes you have to write a code with strong exception-safety guaranty:
void function(std::vector<const char*> &vector)
{
vector.push_back("hello");
try
{
// Do some work
vector.push_back("world");
try
{
// Do other work
}
catch (...)
{
vector.pop_back(); // Undo vector.push_back("world")
throw; // Rethrow the exception
}
}
catch (...)
{
vector.pop_back(); // Undo vector.push_back("hello");
throw; // Rethrow the exception
}
}
But these constructions are quite bulky.
Is there any way to force to run some cleanup code at function exit? Something similar to atexit, but in a function scope...
Is there any way to run some rollback code in case of exception without using nested try/catch blocks?
I would like to have some operators or functions that would work like this:
void function(std::vector<const char*> &vector)
{
int *arr = malloc(1000*sizeof(int));
onexit { free(arr); }
vector.push_back("hello");
onexception { vector.pop_back(); }
// Do some work
vector.push_back("world");
onexception { vector.pop_back(); }
// Do other work
}
If it is possible to create such functions, are there any reasons to avoid using them? Are there such constructs in other programming languages?
I have created macros that implement this functionality. They generate a local variable that runs a cleanup code in the destructor using C++11 lambda functions. The std::uncaught_exception function is used to check if there is any exception currently thrown. Creating the variable itself shouldn't throw any exceptions because a lambda with all variables captured by reference is used to create the variable (such lambdas do not throw exceptions in copy/move constructors).
#include <exception>
// An object of the class below will run an arbitrary code in its destructor
template <bool always, typename TCallable>
class OnBlockExit
{
public:
TCallable m_on_exit_handler;
~OnBlockExit()
{
if (always || std::uncaught_exception())
{ m_on_exit_handler(); }
}
};
// It is not possible to instantiate an object of the 'OnBlockExit' class
// without using the function below: https://stackoverflow.com/a/32280985/5447906.
// Creating of an object of the 'OnBlockExit' class shouldn't throw any exception,
// if lambda with all variables captured by reference is used as the parameter.
template <bool always, typename TCallable>
OnBlockExit<always, TCallable> MakeOnBlockExit(TCallable &&on_exit_handler)
{
return { std::forward<TCallable>(on_exit_handler) };
}
// COMBINE is needed for generating an unique variable
// (the name of the variable contains the line number:
// https://stackoverflow.com/a/10379844/544790)
#define COMBINE1(X,Y) X##Y
#define COMBINE(X,Y) COMBINE1(X,Y)
// ON_BLOCK_EXIT generates a variable with the name
// in the format on_block_exit##__LINE__
#define ON_BLOCK_EXIT(always, code) \
auto COMBINE(on_block_exit,__LINE__) = MakeOnBlockExit<always>([&]()code)
// Below are target macros that execute the 'code' on the function exit.
// ON_FINALLY will allways execute the code on the function exit,
// ON_EXCEPTION will execute it only in the case of exception.
#define ON_EXCEPTION(code) ON_BLOCK_EXIT(false, code)
#define ON_FINALLY(code) ON_BLOCK_EXIT(true , code)
Here is an example how to use these macros:
void function(std::vector<const char*> &vector)
{
int *arr1 = (int*)malloc(800*sizeof(int));
if (!arr1) { throw "cannot malloc arr1"; }
ON_FINALLY({ free(arr1); });
int *arr2 = (int*)malloc(900*sizeof(int));
if (!arr2) { throw "cannot malloc arr2"; }
ON_FINALLY({ free(arr2); });
vector.push_back("good");
ON_EXCEPTION({ vector.pop_back(); });
auto file = fopen("file.txt", "rb");
if (!file) { throw "cannot open file.txt"; }
ON_FINALLY({ fclose(file); });
vector.push_back("bye");
ON_EXCEPTION({ vector.pop_back(); });
int *arr3 = (int*)malloc(1000*sizeof(int));
if (!arr3) { throw "cannot malloc arr3"; }
ON_FINALLY({ free(arr3); });
arr1[1] = 1;
arr2[2] = 2;
arr3[3] = 3;
}
All cleanup code is executed in reverse order (in the order opposite to the order of the ON_FINALLY/ON_EXCEPTION macros appearance in the function). The cleanup code is executed only if control passes beyond the corresponding ON_FINALLY/ON_EXCEPTION macro.
Check the following link to see the output of the demo program execution: http://coliru.stacked-crooked.com/a/d6defaed0949dcc8
C++ has destructors which is what you need. An object that does whatever you need done at scope exit in its destructor that you then create an instance of on the stack in the scope where you need the work done, will get destroyed when the scope is left and then do the work at that time.
ScopeGuard is the right choice for you. It basically calls the function you specify at destructor.
So your code can be:
void your_function() {
scope_guard guard = [&vector]() {
vector.pop_back();
};
// your code
guard.dismiss(); // success
}
Related
I have a function which I would like to have the strong exception guarantee:
class X {
/* Fields and stuff */
void some_function() {
vector1.push_back(/*...*/); // May Throw
vector2.push_back(/*...*/); // May Throw
vector3.push_back(/*...*/); // May Throw
vector4.push_back(/*...*/); // May Throw
}
};
The only way I can think of making this having the strong exception guarantee is the following:
class X {
/* Fields and stuff */
void some_function() {
try { vector1.push_back(/*...*/);};
catch (Vector1PushBackException) {
throw Vector1PushBackException;
}
try { vector2.push_back(/*...*/);};
catch (Vector2PushBackException) {
vector1.pop_back();
throw Vector2PushBackException;
}
try { vector3.push_back(/*...*/);};
catch (Vector3PushBackException) {
vector1.pop_back();
vector2.pop_back();
throw Vector3PushBackException;
}
try { vector4.push_back(/*...*/);};
catch (Vector4PushBackException) {
vector1.pop_back();
vector2.pop_back();
vector3.pop_back();
throw Vector4PushBackException;
}
}
};
However, this is really ugly and error-prone!! Is there a better solution than the one I put above? I can hear someone telling me that I need to use RAII, but I can't figure it out how, since the pop_back operations must not be done when the function returns normally.
I would also like any solution to be zero - overhead on the happy path; I really need the happy path to be as fast as possible.
The solution is to use scope guards.
See this answer for an example implementation of them; I'm not going to repeat it here. With scope guards, your code will look like this:
vector1.push_back(/*...*/);
FINALLY_ON_THROW( vector1.pop_back(); )
vector2.push_back(/*...*/);
FINALLY_ON_THROW( vector2.pop_back(); )
vector3.push_back(/*...*/);
FINALLY_ON_THROW( vector3.pop_back(); )
vector4.push_back(/*...*/);
FINALLY_ON_THROW( vector4.pop_back(); )
Here, FINALLY_ON_THROW is a macro (see link above). Rather than executing it's parameter immediately, it causes it to be executed when you leave the current scope because of an exception. If you instead leave the scope the normal way, the parameter is ignored. If you leave the scope before control reaches the guard in the first place, it's also ignored.
Note that the last guard is superfluous if nothing after it (in the same scope) can throw.
A problem with simply popping back is that it won't necessarily restore the vector to the original state. If adding the element caused any of the vectors to reallocate, then iterators / references to the elements would be invalidated and that invalidation cannot be rolled back making strong exception guarantee impossible.
A safe and simple and general solution is to make the modifications on a copy. Copying of course has an extra cost though.
void some_function() {
auto copy = *this;
copy.vector1.push_back(/*...*/); // May Throw
copy.vector2.push_back(/*...*/); // May Throw
copy.vector3.push_back(/*...*/); // May Throw
copy.vector4.push_back(/*...*/); // May Throw
*this = std::move(copy);
}
HolyBlackCat's scope guard suggestion is an elegant solution in cases where rollback is possible such as if you used another container that doesn't invalidate iterators / references, or if you simply don't care about the invalidation or if you have a class invariant that prevents the function from being called when the capacity is full.
You could feasibly, and at marginal extra cost, first check whether all vectors have extra capacity and choose between copying and rollback based on the check. This allows the caller to not pay the cost of copying if they reserve sufficient capacity beforehand. That does stray further from elegance however.
You can do it in many ways... For example like this:
#include <vector>
#include <type_traits>
#include <exception>
template<class F>
struct on_fail
{
F f_;
int count_{ std::uncaught_exceptions() };
~on_fail()
{
// C++20 is here and still no easy way to tell "unwinding" and "leaving scope" apart
if (std::uncaught_exceptions() > count_) f_();
}
};
template<class F> on_fail(F) -> on_fail<F>;
auto emplace_back_x(auto& v, auto&& x)
{
v.emplace_back(std::forward<decltype(x)>(x));
return on_fail{[&v]{ v.pop_back(); }};
}
int bar();
template<class F>
struct inplacer
{
F f_;
operator std::invoke_result_t<F&>() { return f_(); }
};
template<class F> inplacer(F) -> inplacer<F>;
void foo()
{
std::vector<int> v1, v2, v3;
auto rollback1 = emplace_back_x(v1, 1);
auto rollback2 = emplace_back_x(v2, inplacer{ bar });
auto rollback3 = emplace_back_x(v3, inplacer{ []{ return bar() + 1; } });
}
Note that your example is not correct: if push_back() fails with std::bad_alloc (or any other exception) -- you fail to perform undo step.
Also, perhaps in your case it make sense to use basic guarantee? In practice you can often deal with it on a higher level -- e.g. disconnect and discard entire accumulated state, leaving client to reconnect and repeat attempt.
How about this?
class X {
/* Fields and stuff */
void some_function() {
vector1.push_back(/*...*/); // May Throw
try {
vector2.push_back(/*...*/); // May Throw
try {
vector3.push_back(/*...*/); // May Throw
try {
vector4.push_back(/*...*/); // May Throw
} catch(...) {
vector3.pop_back();
throw;
}
} catch(...) {
vector2.pop_back();
throw;
}
} catch(...) {
vector1.pop_back();
throw;
}
}
};
But... do you really need 4 different vectors?
class X {
/* Fields and stuff */
void some_function() {
vector1234.push_back(std::make_tuple(/*...*/, /*...*/, /*...*/, /*...*/)); // May Throw
}
};
I am using lambdas to initialize some const variables as described in the core c++ guidelines here. In short, the idiom looks like this
const auto a = [&]() {
MyType a;
// complex initialization
return a;
}();
The problem arises when the initialization can throw an exception that can only be handled outside of the lambda, eg because it must cause the function to return early. I want to be able to do something that looks like this
try {
const auto a = [&]() {
MyType a;
// complex initialization
return a;
}();
}
catch { /* doesn't matter what */ } {
// Somehow handle it
// then return or throw
}
// use a
except that I want the object to be usable after the try-catch block when an exception is not thrown.
I could refactor the function so that all code that depends on successful initialization of the object is inside the try block but this scales horribly with multiple objects to initialize.
try {
const auto a = ...;
try {
const auto b = ...;
try...
catch...
}
catch {...} {
...;
}
catch {...} {
...;
}
On the other hand, moving the try-catch block inside the lambda restricts what I can do to handle it. eg it does not allow me to instantly return, break or continue as far as I can tell. It almost feels like the logical solution would be to interleave the assignment with the try block (eg const auto a = try [&]()...) but it does not seem to be supported by the anguage. Am I correct in that this is not supported and if so is there another known idiom that would result in the behavior I need?
Note: I am asking for situations where it is important for the variable to be const or where default construction followed by assignment is impossible so the obvious solution of default constructing outside the try-block and assigning the value inside it is not viable.
It is honestly no different from simple initialization which also may throw. Try not to micro manage your exceptions. Their power is in allowing you to code freely without worrying about errors every single statement. Put all of the code that does a complete job (or operation) in your try{}catch(){}. An exception should abort the whole procedure, not just a single initialization.
try
{
const auto a = [&]() {
MyType a;
// complex initialization
return a;
}();
const auto b = "something else that may throw"s;
const auto c = a_throwing_function();
// Now do stuff with a, b and c safe in the knowledge that
// they are properly constructed and valid
// ... etc ...
}
catch(std::exception const& e)
{
// abort the entire operation
}
I have the following code:
class ClassA
{
public:
ClassA(std::string str);
std::string GetSomething();
};
int main()
{
std::string s = "";
try
{
ClassA a = ClassA(s);
}
catch(...)
{
//Do something
exit(1);
}
std::string result = a.GetSomething();
//Some large amount of code using 'a' out there.
}
I would like the last line could access the a variable. How could I achieve that, given ClassA doesn't have default constructor ClassA() and I would not like to use pointers? Is the only way to add a default constructor to ClassA?
You can't or shouldn't. Instead you could just use it within the try block, something like:
try
{
ClassA a = ClassA(s);
std::string result = a.GetSomething();
}
catch(...)
{
//Do something
exit(1);
}
The reason is that since a goes out of scope after the try block referring to the object after that is undefined behavior (if you have a pointer to where it were).
If you're concerned with a.GetSomething or the assignment throws you could put a try-catch around that:
try
{
ClassA a = ClassA(s);
try {
std::string result = a.GetSomething();
}
catch(...) {
// handle exceptions not from the constructor
}
}
catch(...)
{
//Do something only for exception from the constructor
exit(1);
}
You can use some sort of optional or just use std::unique_ptr.
int main()
{
std::string s = "";
std::unique_ptr<ClassA> pa;
try
{
pa.reset(new ClassA(s));
}
catch
{
//Do something
exit(1);
}
ClassA& a = *pa; // safe because of the exit(1) in catch() block
std::string result = a.GetSomething();
//Some large amount of code using 'a' out there.
}
Of course, just extending the try block to include the usage of a is the simplest solution.
Also, if you were really planning to exit(1) or otherwise abort the program on failure then simply don't put a try block here at all. The exception will propagate up, aborting the program if it is not caught .
One alternative is to use std::optional . This is the same sort of concept as using a pointer, but it uses automatic allocation and so you are less likely to create a memory leak. This is currently experimental status; you can use boost::optional instead if your compiler doesn't have std::experimental::optional:
#include <experimental/optional>
using std::experimental::optional;
using std::experimental::in_place;
// ...
optional<ClassA> a;
try
{
a = optional<ClassA>(in_place, s);
}
catch(...)
{
// display message or something
}
std::string result;
if ( a )
result = a->GetSomething();
I'd like to reiterate though that this is a bit of a spaghetti style and it'd be better to design your code differently so you aren't continually testing whether construction succeeded or failed.
This requires ClassA be movable or copyable. The in_place is a special argument which invokes a perfect forwarding constructor for the remaining arguments. Without in_place you can only give an actual ClassA as constructor argument, it doesn't consider implicit conversions to ClassA. (This is how optional avoids the ambiguity between copy-construction and list-initialization from object of the same type).
Suppose we have some class (call it classs) with the default constructor which can throw some exception. I need to use the object of that class in a function as follows:
try{
classs c;
} catch(bad_init& b){
//log
}
//if the class initialized succesfully
//do some with c
But c is declared in the try's block scope and therefore is not visible in the function scope. How can I do that?
I don't want to wrap the whole function's body because there're some code throwing another kind of exception.
You cannot do this directly. As long as c is in scope, code has the right to assume if contains an alive object of type classs. If the constructor throws an exception, c will not be initialised and that cannot hold.
The correct way to do this is to wrap the entire scope of c in the try block. After all, code which uses c cannot do anything meaningful if c failed to initialise. If some other code later in that block can throw other exceptions and you don't want to catch them, just don't—let them propagate up the stack normally.
If you cannot use this approach is for some reason, you can resort to something like boost::optional and delayed init:
boost::optional<classs> c;
try {
c = classs();
} catch (bad_init&) {
}
Or do something similar manually with std::aligned_storage, placement new and a conditional destructor call.
a workaround is to use std::unique_ptr:
std::unique_ptr<A> a;
try{
a = std::make_unique<A>();
} catch(bad_init& b){
//log
}
if (a){
//do
}
I would simply catch the exception at the level of the caller. No need to make things complicated.
void functionThatThrows()
{
classs c;
// do something with c
}
void callerThatCatches()
{
try {
functionThatThrows();
} catch(...) {
// handle exception
}
}
The simplest way is just to extend the try block until you no longer need your object :
try{
classs c;
//if the class initialized succesfully
//do some with c
} catch(bad_init& b){
//log
}
I'm trying to make my C++ code exception-safe, and got a problem that neither asking friends nor searching web will help.
On my understanding, when creating an object with constructor potentially throw an exception, the code for creation needs to be enclosed with try block and exception handling is done in catch(){}.
If the creation is heap-based(e.g. newed with default allocator), I can place exception handling code near the creation like this:
void f() {
// work unrelated to Hoge object here
try {
Hoge *pHoge = new Hoge(); // could throw an exception
} catch(HogeException& ex) {
// handle exception
}
// rest of work here
}
However, if the creation is stack-based, I can't find ways to do that and resort to code like below due to the scope of try block:
void g() {
// work unrelated to Hoge object here
try {
Hoge hoge; // could throw an exception
// rest of work here
} catch(HogeException& ex) {
// handle exception
}
}
If // rest of work code above is large, the distance of locations between object creation and exception handling could be long, decreasing code readability...
I prefer the exception handling code is near object creation(and maybe that is one of the concepts of try-catch structure). Is there any solutions?
Delegate the // rest of work to a helper function, and pass a Hoge& to that function:
void RestOfWork(Hoge& hoge)
{
// rest of work here
}
void g() {
// work unrelated to Hoge object here
try {
Hoge hoge;
RestOfWork(hoge);
// rest of work here
} catch(HogeException& ex) {
// handle exception
}
}
Incidentally, Hoge hoge(); doesn't do what you think it does. You probably think that you are declaring an object named hoge of type Hoge, and initializing it by calling the default constructor. What you're actually doing is declaring a function named hoge which takes no parameters and returns a Hoge by-value. I've fixed this in my code above.
Edit Indeed, as suggested by #LightnessRacesInOrbit, the construction of the Hoge object can take place in the deferral function as well, such as with:
void RestOfWork()
{
Hoge hoge;
// rest of work here
}
void g() {
// work unrelated to Hoge object here
try {
RestOfWork();
} catch(HogeException& ex) {
// handle exception
}
}
A reasonable way to do this is to use a nullable single-item container, e.g. boost::optional:
void g() {
// work unrelated to Hoge object here
boost::optional<Hoge> opt_hoge;
try {
opt_hoge = boost::in_place<Hoge>();
} catch(HogeException& ex) {
// handle exception
}
Hoge &hoge = *opt_hoge;
// rest of work here
}
If you can't use Boost, std::unique_ptr would work at the cost of a heap allocation:
void g() {
// work unrelated to Hoge object here
std::unique_ptr<Hoge> opt_hoge;
try {
opt_hoge = std::unique_ptr<Hoge>(new Hoge);
} catch(HogeException& ex) {
// handle exception
}
Hoge &hoge = *opt_hoge;
// rest of work here
}