I have the following pattern:
task<Param1^> MyClass::MethodA(String^ s)
{
return create_task([this, s]
{
....
IAsyncOperation<Param1^>^ result = SystemMethod1ReturningParam1(...);
return result;
});
}
IAsyncOperation<Param2^>^ MyClass::MethodB(String^ s)
{
return create_async([this, s]
{
return MethodA(s).then([this](task<Param1^> t)
{
Param1^ p1 = t.get();
....
Param2^ result = SystemMethod2ReturningParam2(p1);
return result ;
});
});
}
I call public MethodB which calls private MethodA. Param1 is standard enum that I cannot change. MethodA create_task my need to return error condition. I cannot return null. MethodB also needs return error condition.
What's the best way to return errors from both methods?
SystemMethod1ReturningParam1 and SystemMethod2ReturningParam2 which are framework system methods can throw exceptions. Where do I catch them?
If you are worried about exceptions, you should always use task-based continuations and wrap the call to task.get() in a try/catch.
Note that the code below (and other C++ code) throws std::exception, but if you are interfacing with WinRT components and you want the exception to propagate, you must re-throw as a Platform::Exception value.
concurrency::task<int> throw_async()
{
return concurrency::create_task([]
{
throw std::exception("oops");
return -1;
});
}
void test_value()
{
// This will crash inside PPL runtime due to unobserved exception
throw_async().then([](int x)
{
OutputDebugString(L"You'll never see this\r\n");
});
}
void test_task()
{
// This will handle the exception correctly
throw_async().then([](concurrency::task<int>& t)
{
OutputDebugString(L"You'll see this\r\n");
try
{
auto val = t.get();
OutputDebugString(L"You'll never see this\r\n");
}
catch (std::exception& ex)
{
auto error = ex.what(); // "oops"
// Need to re-throw if this crosses the WinRT ABI boundary.
// Conversion of 'error' to Platform::String^ omitted for brevity
throw ref new Platform::FailureException(/* error */);
}
});
}
Related
What I'm trying to do is write code that breaks out of a for loop if an exception is thrown. Can this be achieved by simply using return in the catch block? or do I have to use break somehow?
for example, 1. will this function return 0 or 1?
2. will the first return statement break the for loop or
3. will it keep on looping?
Thank you in advance!!
int main() {
for (int i = 0; i < 2; i++) {
try {
if (i = 0) {
throw fake_error;
}
}
catch(fake_error) {
return i;
}
}
return i;
}
Any block can try catch, though while allowed I recommend to use a bigger scope. (exceptions are the biggest exception to the "don't pay for what you don't use" rule in c++).
To avoid having to put your exception into the inner loop you can create your own exception and put the information you want to have available in the catch block inside the exception. So this example shows you how to do that, also catch exceptions by const& this will avoid unecessary copying and/or modification of the exception content.
#include <stdexcept>
//-------------------------------------------------------------------------
// declare/define an exception that can hold an int.
class my_exception :
std::exception
{
public:
// always declare constructors with one parameter explicit
// or they can be used in implicit type-conversions
explicit my_exception(const int value) :
m_value{ value }
{
}
// accessor to data
const int& value() const noexcept
{
return m_value;
}
private:
int m_value;
};
//-------------------------------------------------------------------------
int main()
{
int retval{ 0 };
// with our own exception we can
// move the try-catch block out of the loop.
try
{
for (int i = 0; i < 2; ++i)
{
if (i == 1) throw my_exception(i);
}
}
catch(const my_exception& e)
{
retval = e.value();
}
return retval;
}
Yes.
C++ allows try/catch inside any block of statements, including a for() loop block.
However, you may want to consider doing it otherwise if possible just because it is slow (if the for() is only expected to go over a small number of iterations, then not big deal).
I have some code that looks like this:
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
And it works, but due to changing circumstances, it's now possible for that find() method to throw a "not found" exception, which I need to catch.
What I'd like to write would be
try {
const SomeType & elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
But of course this doesn't work, because elt is no longer in scope by the time its processing block is reached. I can't rearrange this to
const SomeType & elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
because of course reference types in C++ aren't allowed to be uninitialized. So I'm left with the options of temporarily setting elt to be a reference to a dummy object of type SomeType, which I'd rather not do, or nesting the try/catch blocks, like this:
try {
const SomeType & elt = x.find();
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
} catch (...) {
// handle "not found" exception
}
I don't like this, either: the nesting is confusing, and I don't like the way the "not found" exception handler is hiding down there at the end.
Can anyone think of a better way to arrange this? (In C, of course, we'd just have the find function return a null pointer in the not-found case, and handle it that way, but I like to try not to be an old C programmer when I'm writing C++, and anyway x.find() is already set up to return a reference, not a pointer.)
If exceptions are different, you might use the same try block:
try {
const SomeType& elt = x.find();
// ... do something with elt ...
} catch (const NotFoundException&) {
// handle "not found" exception
} catch (...) {
// handle processing exception
}
else rebinding reference is not allowed, but might be simulated by pointer or std::reference_wrapper in general,
And optional reference (not allowed neither in std, but boost allow it) might be simulated by pointer or std::optional<std::reference_wrapper<T>>.
So:
const SomeType* eltPtr = nullptr;
try {
eltPtr = &x.find();
} catch (const NotFoundException&) {
// handle "not found" exception
return;
}
const SomeType& elt = *eltPtr;
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
Split into another function:
void func1()
{
try {
const SomeType & elt = x.find();
func2(elt);
} catch (...) {
// handle "not found" exception
}
}
void funct2(const SomeType & elt)
{
try {
// ... do something with elt ...
} catch (...) {
// handle processing exception
}
}
Though in general I find your interface slightly disturbing to require all these try/catch blocks in the first place. Unfortunately it is hard to offer advice on how to improve the general style with such little information.
It will not be to everyone's taste (the behaviour is defined by the way), but you could use
#include <functional>
std::reference_wrapper<const SomeType> elt = elt;
try {
elt = x.find();
} catch (...) {
// handle "not found" exception
return;
}
Arguably the setting of elt to itself is an abuse of std::reference_wrapper, which has its default and move constructors deleted by design: I'm circumventing that.
Essentially std::refernce_wrapper is a pointer under the hood but you can rebind it, which is essentially what you want to do here.
Consider the following resource managing class
class FooResouce
{
public:
explicit FooResouce(T arg_to_construct_with)
{
m_foo = create_foo_resouce(arg_to_construct_with);
if(m_foo == nullptr)
{throw SomeException(get_foo_resource_error(), arg_to_construct_with);}
}
// Dtor and move operations
// Other FooResource interaction methods
private:
foo_resource_t* m_foo;
};
Now, when we decide to catch the exception and format an error message, it's easy to know what caused the exception at the fundamental level, but we have no information about where the exception was triggered in the upper level. Here upper level refers the function that tried to create a FooResource, or any function above that stack frame. How would you add context to the error in case that is needed:
Pass some optional context information as an extra argument to the Ctor, which can then be stored in the exception
At callsite use a pushContext function. This function will store the context using thread-local storage.
Catch and rethrow. I think the code would be ugly in this case.
Although this solution conflicts with your third requirement 3: No Catch and rethrow, I propose an solution with std::nested_exception and macros because this seems to provide a reasonable solution for the current problem at least to me.
I hope this too long answer can help you.
1. An Error Handling with std::nested_exception
First, we can recursively nest exceptions using std::nested_exception.
Roughly speaking, We can add exceptions of arbitrary types to this class by calling std::throw_with_nested.
These enables us to carry all information of thrown exceptions with a rather simple code, just throwing each exception by std::throw_with_nested in each ellipsis catch handler catch(…){ } in the upper level.
For instance, following function h throws a std::nested_exception which aggregates the user-defined exception SomeException and std::runtime_error:
struct SomeException : public std::logic_error {
SomeException(const std::string& message) : std::logic_error(message) {}
};
[[noreturn]] void f(){
std::throw_with_nested(SomeException("error."));
}
[[noreturn]] void g()
{
try {
f();
}
catch (...) {
std::throw_with_nested(std::runtime_error("Error of f."));
}
};
[[noreturn]] void h()
{
try {
g();
}
catch (...) {
std::throw_with_nested(std::runtime_error("Error of g."));
}
}
Locating Exceptions (Fundamental Level)
Replacing all of these std::throw_with_nested by the following function throw_with_nested_wrapper through the macro THROW_WITH_NESTED, we can make records of the file names and the line numbers where exceptions occurred.
As is well known, __FILE__ and __LINE__ are pre-defined by C++ standard.
So the macro THROW_WITH_NESTED has a key role to add these location information:
// "..." are arguments of the ctor of ETYPE
// and the first one must be a string literal.
#define THROW_WITH_NESTED(ETYPE, ...) \
throw_with_nested_wrapper<ETYPE>(__FILE__, __LINE__, __VA_ARGS__);
template<typename E, typename ...Args>
[[noreturn]]
void throw_with_nested_wrapper(
char const* fileName,
std::size_t line,
const std::string& message,
Args&& ...args)
{
auto info = std::string(fileName)
+ ", l." + std::to_string(line) + ", "
+ message;
std::throw_with_nested(E(info, std::forward<decltype(args)>(args)...));
};
Locating Exceptions (Upper Level)
If we have to pick up information about where the exception was triggered in the upper level, the following macro HOOK reusing the above macro THROW_WITH_NESTED would work for us:
#define HOOK(OPERATION) \
[&]() \
{ \
try{ \
return OPERATION; \
} \
catch(...){ \
auto info = std::string(#OPERATION) + ", upper level."; \
THROW_WITH_NESTED(std::runtime_error, info); \
} \
}()
Finally, first three functions f, g and h are rewritten and simplified as follows:
[[noreturn]] void f(){
THROW_WITH_NESTED(SomeException, "SomeException, fundamental level.");
}
void g(){
HOOK(f());
};
void h(){
HOOK(g());
}
Extracting Error Information
Extracting all explanatory information of nested exceptions is a simple task.
Passing the caught exception at the most outer try-catch block into the following function output_exceptions_impl, we can do it.
Each nested exception can be recursively thrown by std::nested_exception::rethrow_nested.
Since this member function calls std::terminate when there is no stored exception, we should apply dynamic_cast to avoid it as pointed out in this post:
template<typename E>
std::enable_if_t<std::is_polymorphic<E>::value>
rethrow_if_nested_ptr(const E& exception)
{
const auto *p =
dynamic_cast<const std::nested_exception*>(std::addressof(exception));
if (p && p->nested_ptr()){
p->rethrow_nested();
}
}
void output_exceptions_impl(
const std::exception& exception,
std::ostream& stream,
bool isFirstCall = false)
{
try
{
if (isFirstCall) { throw; }
stream << exception.what() << std::endl;
rethrow_if_nested_ptr(exception);
}
catch (const std::runtime_error& e) {
stream << "Runtime error: ";
output_exceptions_impl(e, stream);
}
/* ...add further catch-sections here... */
catch(...){
stream << "Unknown Error.";
}
}
BTW, explicit try-catch blocks at the most outer places are rather verbose and thus I usually use the following macro proposed in this post:
#define CATCH_BEGIN try{
#define CATCH_END(OSTREAM) } catch(...) { output_exceptions(OSTREAM); }
void output_exceptions(std::ostream& stream)
{
try {
throw;
}
catch (const std::exception& e) {
output_exceptions_impl(e, stream, true);
}
catch (...) {
stream << "Error: Non-STL exceptions." << std::endl;
}
}
Then all exceptions thrown from h can be traced and printed by the following code.
Inserting the macros THROW_WITH_NESTED, HOOK, CATCH_BEGIN and CATCH_END at the right lines of our code, we can locate exceptions in each thread:
CATCH_BEGIN // most outer try-catch block in each thread
...
HOOK(h());
...
CATCH_END(std::cout)
Then we get the following output where file names and line numbers are just an examples.
All the available information is recorded:
DEMO with 2 threads
Runtime error: prog.cc, l.119, h(), upper level.
Runtime error: prog.cc, l.113, g(), upper level.
Runtime error: prog.cc, l.109, f(), upper level.
Logic error: prog.cc, l.105, SomeException, fundamental level.
2. In case of FooResouce
First requirement is
Pass some optional context information as an extra argument to the Ctor, which can then be stored in the exception
Let us define the following special exception class SomeException which contains some optional context information and the member function getContext to get it:
class SomeException : public std::runtime_error
{
std::string mContext;
public:
SomeException(
const std::string& message,
const std::string& context)
: std::runtime_error(message), mContext(context)
{}
const std::string& getContext() const noexcept{
return mContext;
}
};
Adding a new argument context to FooResouce::FooResouce and replacing throw by THROW_WITH_NESTED, we can pass the first requirement within the above error handling framework:
class FooResouce
{
public:
FooResouce(
T arg_to_construct_with,
const std::string& context)
{
m_foo = create_foo_resouce(arg_to_construct_with);
if(!m_foo){
THROW_WITH_NESTED(SomeException, "Ctor failed.", context);
}
...
}
...
};
Next,
but we have no information about where the exception was triggered in the upper level. Here upper level refers the function that tried to create a FooResource,
Creating each FooResource with HOOK, we can get information about where the ctor was failed in the upper level.
The caller side would be as follows.
In this manner, all error information including messages, contexts and their locations would be clarified in each thread.
CATCH_BEGIN // most outer try-catch block in each thread
...
auto resource = HOOK(FooResouce(T(), "context"));
...
CATCH_END(std::cout)
Finally,
At callsite use a pushContext function. This function will store the context using thread-local storage.
Although I don't know the detail of this requirement, but since we can call SomeException::getContext in output_exceptions_impl as follows and get all contexts from every thrown SomethingExceptions, I think we can also store them like this:
DEMO(my proposal)
void output_exceptions_impl(
const std::exception& exception,
std::ostream& stream,
bool isFirstCall = false)
{
...
catch (const SomeException& e) { // This section is added.
stream
<< "SomeException error: context:"
<< e.getContext() << ", "; // or pushContext?
output_exceptions_impl(e, stream);
}
...
}
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
}
When trying to encapsulate C API in C++ method, i found a problem in throwing an exception:
int status;
char* log = nullptr;
int infoLogLength;
getFooStatus(&status);
getFooLogLength(&infoLogLength);
if (!status) {
log = new char[infoLogLength];
getFooLog(infoLogLength, log);
throw std::runtime_error(log);
}
I am not allowed to modify the interface methods in any way.
From what i understand, i am required to reserve memory for the method to fill, and operate on that. However, throwing the exception will return from the method, not letting me to free the resources. Is my code correct, or should i go around this in some other way?
std:runtime_error expects a std::string, so give it a std::string instead of a char*:
int status;
getFooStatus(&status);
if (!status) {
int infoLogLength;
getFooLogLength(&infoLogLength);
std::string log(infoLogLength, '\0');
getFooLog(infoLogLength, &log[0]);
throw std::runtime_error(log);
}
Alternatively, you can pass a char*, simply allocate it in a way that promoted auto-freeing, eg:
int status;
getFooStatus(&status);
if (!status) {
int infoLogLength;
getFooLogLength(&infoLogLength);
std::vector<char> log(infoLogLength);
getFooLog(infoLogLength, &log[0]);
throw std::runtime_error(&log[0]);
}
As far as I know runtime_error has two overloads, one with a const *char and another as const string&.
I believe constructing a std::string as a local variable and passing that to runtime_error should result in it being cleaned up properly.
There is a simple way to deal with exceptions, without having to refactor the code so that the array is managed by an object whose destructor cleans it up. Namely:
char* log = nullptr;
try {
int status;
int infoLogLength;
getFooStatus(&status);
getFooLogLength(&infoLogLength);
if (!status) {
log = new char[infoLogLength];
getFooLog(infoLogLength, log);
throw std::runtime_error(log);
}
} catch (...) { // special C++ syntax: "catch any exception"
delete [] log;
throw; // special C++ syntax: "re-throw" current exception
}
If all you have is a single catch (...), it looks a lot as if C++ supports finally. The difference betwen catch (...) and a finally feature is that catch (...) does not execute unconditionally: it only executes if there isn't a more specific catch. So, if you were to add additional catch clauses in the same try block, they would all have to repeat the delete [] log clean-up action.
This could be mitigated by using nesting:
try { // real exception-handling try
try { // try for unwind protection only
...
} catch (...) {
// clean-up statements
throw;
}
} catch (actual_error &err) {
...
} catch (another_exc_type &exc) {
...
}