Set exception on promise without using std::current_exception - c++

In C++ reference regarding the set_exception method , the example uses std::current_exception. To do that you have to throw and catch your exception:
std::thread t([&p]{
try {
// code that may throw
throw std::runtime_error("Example");
} catch(...) {
try {
// store anything thrown in the promise
p.set_exception(std::current_exception());
// or throw a custom exception instead
// p.set_exception(std::make_exception_ptr(MyException("mine")));
} catch(...) {} // set_exception() may throw too
}
});
This throwing and catching is obviously tedious, but the method accepts a std::exception_ptr. I was wondering whether it's possible to set a specific exception directly. I imagine the problem would be that a local exception object would have lifetime issues if we pass around a pointer to its address and allocating a new exception object would leave memory leaks. Is there a way ?

Related

Level of exception handling / rethrowing an exception

I have a function that basically returns an element from a vector using at(size_type pos). at() throws an std::out_of_range exception in case of an invalid (out_of_range) position.
I basically want this exception to be propagated to the caller, so that it can be handled on that level. Would the rethrow that I've added to my getter be necessary? Or would I get the same effect by just omitting the try-catch altogether?
int MyClass::GetNumber(size_t a_Idx) const
{
// Is the following try-catch-rethrow necessary? Or can the whole try-catch be omitted?
try
{
return m_Numbers.at(a_Idx);
}
catch (const std::out_of_range&)
{
// A throw expression that has no operand re-throws the exception currently being handled
throw;
}
}
MyClass m;
try
{
int t = m.GetNumber(42);
}
catch(const std::out_of_range&){}
I tried both, and didn't notice any difference, but I wonder whether I'm lucky, or whether this is guaranteed.
The exception thrown by std::vector::at(), as any other exception (someone correct me if I'm wrong), will unwind the stack until it reaches a try-catch block where it is caught, or cause an unhandled exception error if it isn't caught at any level.
Therefore, if your only intent is to catch it at the caller level, without any intermediate exception handling, there is no need to catch it in place and rethrow it: it will reach the caller's try-catch block, provided no intermediate try-catch block handles it.
It's guaranteed.
Exceptions bubble up until something catches them… unless nothing catches them, then your program aborts instead.
So, you do not need to explicitly re-throw through each scope.
Re-throwing would be useful if you had some extra work to do in that catch block before proceeding to let the exception bubble up as it was going to anyway.
Don't forget to note in your documentation that GetNumber(size_t) can throw std::out_of_range.

Will throwing an exception in a catch block lead to two exceptions being in flight? [duplicate]

This question already has answers here:
Nested try...catch inside C++ exception handler?
(2 answers)
Closed 1 year ago.
Consider the following C++ code:
class MyException {};
void someFunction()
{
try
{
/// ... code that may throw
}
catch(std::exception& e )
{
throw MyException();
}
}
Question
Is the exception e absorbed at the beginnging of the catch block or at the end of the catch block?
In the second case throwing the new exception would result in having two exceptions in flight, what is not what I want. I want to absorb the std::exception and start one of my own type.
No. That's how one should do it. The throw myException() can only occur if the first exception has been caught and hence is no longer 'in flight'.
This design pattern is quite common to 'translate' error messages coming from another library that your code is using to an error that the user of your code can better relate to.
Alternatively, if you want to do more than merely throw (say you want to do some clearing up of resources -- though that should really be done via RAII, i.e. from destructors), then you can simply rethrow the original exception via
try
{
// ... code that may throw
}
catch(...) // catches anything
{
// ... code that runs before rethrowing
throw; // rethrows the original catch
}
just throw; statement is enough in catch block to rethrow same exception in higher context.
It throws SAME exception again. No new exception is generated. So no fight :)
In case you want to catch exception of type A and then throw exception of type B, then the way you did it is absolute correct.
In this case, old exception (type A) is caught(absorbed) and only new exception(type B) is thrown to higher context. So, again no fight :)

Why rethrow an exception

In C++, why would you want to rethrow an exception. Why not let the current catch block handle the exception. For what reasons would you rethrow an exception to another try/catch block?
An exception is thrown when a function cannot meet its contract (what it promises the caller it will do). When a function calls another function that throws an exception, there are four main approaches to how it might respond:
Catch the exception and handle it. This should only be done if the function is able to meet its contract despite the exception being thrown. If it catches the exception but fails to meet its contract, it is hiding a problem from the calling code.
Allow the exception to propagate. This should be done if the exception cannot be handled by this function (that is, the function is unable to meet its contract because the exception has been thrown), and if the exception exposes the appropriate information to the calling code.
Catch the exception, do some clean-up and/or add extra info, and rethrow it. This should be done if the exception cannot be handled by this function, but it needs to do some cleaning up before propagating it. It can also provide extra information to help with handling/debugging the exception (I often think of the programmer as the very last exception handler).
Catch the exception and throw a different exception (perhaps wrapping the original). This should be done if the exception cannot be handled by this function, but a different exception better expresses the problem to the calling code.
Why not let the current catch block handle the exception. For what reasons would you rethrow an exception to another try/catch block?
The idea behind exceptions is that you throw them at the error site and handle them down the stack, where you have enough information to handle the error.
Conversely, there are cases when you must do something in case of an error, but still don't know how to handle the error (this is the case when you rethrow).
Example:
void connect_and_notify(int connection_data)
{
try
{
create_network_connection(connection_data); // defined somewhere else
notify("connection open"); // same (notify event listeners)
}
catch(const std::runtime_error&)
{
notify("connection failed");
throw;
}
}
Client code:
void terminal_app_controller()
{
try
{
connect_and_notify(1);
}
catch(const std::runtime_error& err)
{
std::cerr << "Connection failed;\n";
exit(1); // this is usually bad bad code but whatever
}
}
void ongoing_server_controller()
{
bool connected = false;
int connection = 1;
while(!connected)
{
try
{
connect_and_notify(1);
connected = true;
}
catch(const std::runtime_error&)
{
connection++;
}
}
}
In the two usage scenarios, the error is handled differently (connect_and_notify has no way of knowing that, but still, on a failed connection it must notify listeners).
Each function has a different policy to handle the exception and this means different catch blocks.
I very much dislike anything like
catch (std::exception&) {
... // do some cleanup
throw;
}
RAII is the correct solution to that problem. Even:
catch (std::exception&) {
... // do some logging here
throw;
}
can be handled with RAII, although it is less intuitive.
BUT - where I have rethrown is any situation where 3rd-part (or vendor-supplied) code throws "generic" exceptions with state. For example, when logging telematics messages to a database, I know that I often receive duplicate copies of the same message. Each message has a unique ID - so a primary key violation in my DB is an "innocent" error that should be silently ignored.
Unfortunately, the DB framework we use doesn't throw a specific exception for PK violations - so we need to catch the generic dbexception and check what its reason code is to decide what to do. Hence:
catch (db::exception& e) {
if (e.reason != db::exception::reason::pk_violation)
throw;
}
Also, piwi mentioned internal state. An example would be
for (;;) {
try {
...
}
catch (some_exception& e) {
if (retry_count > 3)
throw;
}
}
Remember: If you are going to rethrow, always catch by reference to avoid slicing the exception object. (You should usually catch by ref anyway, but it is even more important when rethrowing)

C++ catching exception in constructor

How can I protect myself from using object which isn't fully created when using exceptions?
Should I catch in constructor ? Or maybe it's bad practice ? If I'll catch in constructor object will be created.
#include <stdio.h>
class A
{
public:
A()
{
try {
throw "Something bad happened...";
}
catch(const char* e) {
printf("Handled exception: %s\n", s);
}
// code continues here so our bad/broken object is created then?
}
~A()
{
printf("A:~A()");
}
void Method()
{ // do something
}
};
void main()
{
A object; // constructor will throw... and catch, code continues after catch so basically we've got
// broken object.
//And the question here:
//
//* is it possible to check if this object exists without catching it from main?
// &object still gives me an address of this broken object so it's created but how can I protect myself
// from using this broken object without writing try/catch and using error codes?
object.Method(); // something really bad. (aborting the program)
};
The language itself has no concept of an object being "invalid" in any detectable way.
If the exception indicates that a valid object can't be created, then it shouldn't be handled within the constructor; either rethrow it, or don't catch it in the first place. Then the program will leave the scope of the object being created, and it won't be possible to incorrectly access it.
If that isn't an option for some reason, then you'll need your own way to mark the object as "invalid"; perhaps set a boolean member variable at the end of the constructor to indicate success. This is flaky and error-prone, so don't do it unless you've got a very good reason.
If the object is in an invalid state when a certain exception is thrown, then I would let the exception unwind the call stack so the caller can be notified (and therefore react) to such things.
However, if the exception is one you can recover from, it may be worth trying to do so depend on your application. Make sure you use something like a logger or even simply stderr to indicate this is happening though.
I am going to suggest a first iteration of doing something more like this:
try {
throw "Something bad happened...";
}
catch(const std::exception e) {
cerr << e.what () << endl ; // Better off in the main
throw ;
}
Two things here:
Unless your exception handler handles the exception, it should throw.
Always use exception classes based upon std::exception to that you can always find out what the problem was as shown above.

Is the C++ exception out of scope if caught by the outter level caller?

I did bit of researching while trying to find proper way to implement exceptions in my code I came accross
Throw by value, catch by reference
to be the recommended way of deal exceptions in C++ . I have a confusion about when the exception thrown gets out of scope.
I have following exception hierarchy
ConnectionEx is mother of all connection exceptions thrown by dataSender
ConnectionLostEx is one of the subclasses of ConnectionEx
so here is a sample code. In words DataSender instance is member of DataDistrubutor who calls functions on dataSender for example send() and DataSender throws ConnectionEx's subclasses as exceptions in case of problems.
// dataSender send() function code chunk
try
{
// some problem occured
// create exception on stack and throw
ConnectionLostEx ex("Connection lost low signals", 102);
throw ex;
}
catch(ConnectionLostEx& e)
{
//release resources and propogate it up
throw ;
}
//A data distributor class that calls dataSender functions
try
{
// connect and send data
dataSender.send();
}
catch(ConnectionEx& ex)
{
// free resources
// Is the exception not out of scope here because it was created on stack of orginal block?
//propogate it further up to shows cause etc..
}
In C# or java we have a pointer like reference and that it valid all the way up, I am confused about the scope of exceptions given the exception is thrown by value when exactly does it get out of scope ??? and when caught as parent type ConnectionEx in this case can this be casted to get the real one back somwhere up in the chain of catch blocks ??
A copy of the exception is thrown, not the original object. There's no need to instantiate a local variable and throw it; the idiomatic way to throw an exception is to instantiate it and throw it on the same line.
throw ConnectionLostEx("Connection lost low signals", 102);