Dealing with specific exceptions - c++

I have a piece of network code that throws various exception which are all caught under a general catch exception statement.
try {
network code
} catch (Exception e) {
freeaddrinfo(some_address);
}
The problem with this method is the freeaddrinfo within the exception. Not all cases of exception can/should call freeaddrinfo and in my specific case freeaddrinfo should not be called when there is an invalid address that is passed into the network code to connect somewhere. My idea of solving this problem is to retrieve the error code that was thrown by this exception and to possibly use this in combination with e.to_string to deal with this edge case. From what I have learned from Effective Java, this is a fragile way of dealing with this problem. What do you recommend I should do?

In C++, the usual way to release a resource after an exception is not to catch the exception, but to wrap the resource in an object whose destructor is responsible for releasing. That way, it is released when the management object goes out of scope (or is otherwise destroyed), whether or not an exception is thrown. This technique is known as RAII.
A (very basic) management object might look like:
struct AddressInfo {
addrinfo * info;
// Constructor takes ownership of resource
explicit AddressInfo(addrinfo * info) : info(info) {}
// Destructor releases resource
~AddressInfo() {freeaddrinfo(info);}
// Prevent shallow copying, so only one object manages the resource
AddressInfo(AddressInfo const &) = delete;
void operator=(AddressInfo const &) = delete;
};
Then your code would become:
// some network code
AddressInfo address(some_address);
// some more network code
with no need for any exception handling or manual clean-up code.

If you insist on using exceptions, then the network code should raise a very specific exception (type) based on the nature of the error. That is, the network code should raise an exception that, by its very nature, implies whether freeaddrinfo() can be invoked.

Create more specific exceptions and throw them? Then you can catch those first, before falling back on the general catch.
try {
network code
}
catch (SomeException1 e) { freeaddrinfo(some_address); }
catch (SomeException2 e) { freeaddrinfo(some_address); }
catch (Exception e) { }

Related

Catch(...) with unknown object - how do I identify what was thrown?

I have a library I use that throws something, but I don't know how to identify what was being thrown.
Sample code to reproduce this:
int main()
{
char* memoryOutOfBounds;
unsigned __int64 bigNumber = -1;
try {
throw std::string("Test");
memoryOutOfBounds = new char[bigNumber];
}
catch (const std::bad_alloc& ex)
{
printf("Exception: %s\n", ex.what());
}
catch (...)
{
printf("Unknown.\n");
}
return 0;
}
The new char[bigNumber] will throw a std::bad_alloc, which is derived from std::exception and will enter the first branch. The other one, throw std::string will enter the second branch. How can I check the object that was thrown? I tried with a catch(void*) in the hopes to catch any object in memory, but that did not happen, so how can I find out what was thrown and from there debug what may have caused this?
catch (...) {}
means: Catch absolute everything that was thrown and drop it. This is only meant as a safeguard, so no exceptions fly out of the window and bring down the whole house. (Aka: Application Termination by Unhandled Exception")
There is no way to tell what was thrown in here.
But as you actually know that an std::string can be thrown, you can catch it in a
catch (const std::string& s) {}
block. You do need to know what (type) was thrown whenever you want to catch exceptions.
However, most libraries which add their own types for exceptions will have them inherit from std::exception. Therefore a
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
block should get them.
If they do not inherit from std::exception and/or block the what() method, it is a stupid way to make the usage of their library extra difficult.
However, somewhere in the documentation of the library the exception throwing behaviour should be explained.
Edit : I think that Point 1. under "How should I design my exception classes" on the Boost Error Handling document is something every library developer should keep in mind. And hopefully the developers of your library did keep that principle in mind. ;-)
There really is no standard C++ way to query any information about the exception that is being thrown. Which is unfortunate, because the runtime has that information in order to match catch blocks. But there is just no access to that information in user code.
If it's purely for research purposes, like just finding out what the type is because the library you're using lacks documentation, you could use std::current_exception() to get a std::exception_ptr object that stores (or references) the thrown exception internally. This type is implementation-defined, but your debugger might happen to provide you with enough information.
#include <exception>
void foo()
{
try
{
function_that_throws();
}
catch(...)
{
std::exception_ptr p = std::current_exception();
// break here and inspect 'p' with a debugger
}
}
This stackoverflow post would be helpful-
C++ get description of an exception caught in catch(...) block
Since C++11 you can capture the current exception with a pointer:
std::exception_ptr p; // default initialization is to nullptr
try {
throw std::string("Test");
}
catch(...)
{
p = std::current_exception();
}

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

What happens if I use "throw;" without an exception to throw?

Here's the setup.
I have a C++ program which calls several functions, all of which potentially throw the same exception set, and I want the same behaviour for the exceptions in each function
(e.g. print error message & reset all the data to the default for exceptionA; simply print for exceptionB; shut-down cleanly for all other exceptions).
It seems like I should be able to set the catch behaviour to call a private function which simply rethrows the error, and performs the catches, like so:
void aFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void bFunction()
{
try{ /* do some stuff that might throw */ }
catch(...){handle();}
}
void handle()
{
try{throw;}
catch(anException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(anotherException)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
catch(...)
{
// common code for both aFunction and bFunction
// involving the exception they threw
}
}
Now, what happens if "handle" is called outside of the exception class.
I'm aware that this should never happen, but I'm wondering if the behaviour is undefined by the C++ standard.
If handle() is called outside the context of an exception, you will throw without an exception being handled. In this case, the standard (see section 15.5.1) specifies that
If no exception is presently being handled, executing a throw-expression with no operand calls terminate().
so your application will terminate. That's probably not what you want here.
If you use throw inside of a catch block, it will rethrow the exception. If you use throw outside of a catch block, it will terminate the application.
Never, never, never use catch(...) as you might catch application errors that you don't want to catch, e.g. bugs, access violations (depending on how you compiled).
Read the great John Robbins book (Debugging Windows Applications) in which he explains more in detail why you shouldn't do it.