I'm using the asio networking library. I'm seeing a very strange behaviour where the debugger tells me that the call to std::map::at() throws an out_of_range exception, however I have catch block to catch precisely that type of exception!
The map in question is this:
/*Both of these maps are global variables in the namespace cloud*/
map<string, weak_ptr<session> > cloud::services;
map<string, vector<weak_ptr<session> > > cloud::subscribed; //this one
And the code that's throwing the exception is this:
void session::subscribirse(std::string a_which)
{
try
{
//We obtain a reference to the group of sockets subscribed to this service name
vector<weak_ptr<session>>& grupo = cloud::subscribed.at(a_which); //HERE
grupo.emplace_back(shared_from_this() );
}
catch(out_of_range& e) //The group didn't exist (no-one had subscribed to it yet)
{
vector<weak_ptr<session>> new_group;
new_group.emplace_back(shared_from_this());
cloud::subscribed.emplace(make_pair(a_which, new_group));
}
catch(...)
{
cout << "unexpected exception during subscribe\n";
}
subscriptions_.emplace_back(a_which);
consumed_ = true;
}
Could the catch-block be rethrowing and the debugger not being capable of detecting that? (I really don't think so).
Sorry if question is not clear, I've spent the last 6 hours and I'm feeling desperate.
The [] operator will insert an empty value if it doesn't already exist and doesn't throw.
cloud::subscribed[a_which].emplace_back(shared_from_this() );
You can check for the existence of a key using find():
if(cloud::subscribed.find(a_which) != cloud::subscribed.end())
Finally, how certain are you that it's throwing an out of bounds exception and not another exception?
Related
I a couple of C++ examples I've seen throw 1 in catch block. Tried to find out what it may be, but always found a classical example with exception object or rethrowing an exception without any argument.
Also sometimes I can find in Internet other examples, also without explanations:
throw 1
throw 2
throw -1
Tell me please what it may mean.
Tell me please what it may mean.
It means you're throwing a value of a int that has the value 1, 2 or -1.
Of course, without any further detail, it's hard to infer a meaning on this.
A use case would be to report error code from a function:
int returning_error_code() {
try {
stuff();
} catch (int e) {
return e; // return error code
}
return 0; // no error
}
throw 1
throw 2
throw -1
Tell me please what it may mean.
throw throws an object. throw 1 throws an object if type int with the value 1. I assume the reader can extrapolate what the other two mean.
This is an exception mechanism. The thrown object can be caught:
try {
throw 1;
} catch (int e) {
std::cout << "an integer was thrown and caught. here is the value: " << e;
}
I've seen throw 1 in catch block.
Throwing inside an exception handler is allowed. It has same behaviour as throwing outside a handler.
always found a classical example with exception object or rethrowing an exception without any argument.
This is a case of throwing an exception object.
There is no limitation to the type of objects that can be thrown. The standard library follows the convention of throwing only classes derived from std::exception. Following this convention in user programs is recommended.
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();
}
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 :)
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)
I am new to programming and am having trouble with try / catch clauses.
Here is an example from a textbook that I have:
int main( )
{
char *ptr;
try {
ptr = new char[ 1000000000 ];
}
catch( … ) {
cout << "Too many elements" << endl;
}
return 0;
}
I have tried to look online for a further explanation and the textbook does not exactly tell me what what these clauses actually do or what it is used for.
Any information would be helpful.
EDIT: The textbook I am using is:
C++: Classes and Data Structures by Jeffrey Childs
A try-catch is the C++ construct for exception handling. Google 'C++ exceptions'.
Try catch is a way of handling exceptions:
try
{
// Do work in here
// If any exceptions are generated then the code in here is stopped.
// and a jump is made to the catch block.
// to see if the exception can be handled.
// An exception is generated when somebody uses throw.
// Either you or one of the functions you call.
// In your case new can throw std::bad_alloc
// Which is derived from std::runtime_error which is derived from std::exception
}
// CATCH BLOCK HERE.
The catch block is where you define what exceptions you want to handle.
// CATCH BLOCK
catch(MyException const& e)
{
// Correct a MyException
}
catch(std::exception const& e)
{
// Correct a std::exception
// For example this would cat any exception derived from std::exception
}
You can have as many catch blocks as you like. If you exception matches any of the catch expressions in the catch statement then the associated block of code is executed. If no catch expressions matches an exception then the stack is unwound until it finds a higher level catch block and the processes is repeated (this can cause the application to exit if no matching catch block is found).
Note: If multiple catch expressions match then the lexically first one is used. Only one or none of the catch blocks will be executed. If none then the compiler will look for a higher level try/catch.
There is also a catch anything clause
catch(...)
{
// This is a catch all.
// If the exception is not listed above this will catch any exception.
}
So how does this apply to your code.
int main( )
{
char *ptr;
try
{
// This calls ::new() which can potentially throw std::bad_alloc
// If this happens then it will look for a catch block.
ptr = new char[ 1000000000 ];
// If the ::new() works then nothing happens and you pointer `ptr`
// is valid and code continues to execute.
}
catch( … )
{
// You only have one catch block that catches everything.
// So if there are any statements that generate an exception this will catch
// the excetption and execute this code.
cout << "Too many elements" << endl;
}
// As you have caught all exceptions the code will continue from here.
// Either after the try block finishes successfully or
// After an exception has been handled by the catch block.
return 0;
}
Try-catch blocks are used to trap errors in the code.
At the most basic level, errors occur because the program tries to execute an invalid instruction. That instruction (read: line of code) could be invalid for a number of reasons. In your specific instance, the instruction could be invalid if your program was not able to allocate 1,000,000,000 bytes of memory to story your ptr. The most common exception is trying to access a bad pointer, which is called a Null Pointer Exception, which occurs when you try to perform some action on an Object that either has not been created, or has been deleted (or got corrupt). You will learn to hate that exception.
Using catch(...) tells the program to execute the code inside the catch block if any error occurs inside the code within the try block. There you can handle your error and try to find someway to either fix the error condition or gracefully exit that module.
You can also catch specific errors, which you can find out more about here : http://www.cplusplus.com/doc/tutorial/exceptions/
If you already know C, try/catch achieves the same thing as setjmp/longjmp when used for error handling. Think of try as code for the if condition of setjmp and catch code for else of setjmp. This makes longjmp equivalent to throw in C++, which is used to throw an exception. In your example, probably, the new operator, which calls some memory allocation function internally, throws an exception on seeing a very large number as input by using the C++ throw operator.
void a()
{
.......
longjmp(buf,1); // <--- similar to throw
.......
}
if ( !setjmp(buf) ) // <--- similar to try
{
.......
a();
.......
}
else // <--- similar to catch
{
.......
}
try/catch is a bit more sophisticated than setjmp/longjmp, as for setjmp/longjmp you will need to declare variables which are modified in between setjmp/longjmp calls as volatile, which is not necessary for try/catch.