Access variable outside try-catch block - c++

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).

Related

When using lambdas for complex initialization of variables, how can I handle outside of the lambda exceptions that are thrown from inside?

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
}

How do I run a cleanup code on the function exit?

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
}

Default initialization throws exception

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
}

Can exception handling of object whose constructor throw an exception be near its stack-based creation on code?

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
}

Object creation in constructor

I somehow read that it is bad style to do object-creation in a constructor ... however, I forgot why it was considered to be bad style (especially when using dependency injection).
Here an example of object-creation in the constructor as pseudo-code:
Myclass
{
Myclass(MyMemberFactory& fac)
{
for(Some criteria)
push_back(fac.createMyMemberType());
}
vector<MyMemberType*> getMyMember();
{
return myMember_;
}
...
private:
vector<MyMemberType*> myMember_;
}
So you can use unit-testing without problems, because you can mock-away the MyMemberFactory.
If I would move the for-loop in an seperated initialize-method, it would be necesarry to check for double-initialisation, and all getters would need first to ckeck, if initialisation already was done. Here the code, by using a seperate initialisation:
Myclass
{
Myclass() : isInitialized_(false)
{
}
void initialize(MyMemberFactory& fac);
{
if(isInitialized_)
throw "Error: Double-Init is not permitted.";
for(Some criteria)
push_back(fac.createMyMemberType());
isInitialized_ =true;
}
vector<MyMemberType*> getMyMember();
{
if(isInitialized_)
throw "Initialize first!";
return myMember_;
}
...
private:
vector<MyMemberType*> myMember_;
bool isInitialized_;
}
So do know any reason, why I should use the second approach over the first approach? Or maybe I just had something wrong in mind, and the first approach is perfectly ok?
If the constructor throws an exception, the destructor will not be called, thus you will lose all the memory that you manually allocated.
The first approach is actually fine. It's not that object creation in a constructor is problematic, it's that doing so with a constructor is problematic. So
Myclass()
{
MyMemberFactory fac;
for(Some criteria)
push_back(fac.createMyMemberType());
}
Would be problematic since clients can no longer use a different factory (for testing, for instance).