exception handling - c++

Sorry, I did not provide the code when I posted earlier, due to the indentation. Now, I am providing the code. As I mentioned earlier, I threw an exception inside the sample code, and i still have a 0 which is returned by the code. I have spent some times trying to figure out, but I could not come with the exact answer.
#include <stdexcept>
#include <iostream>
#include <string>
using namespace std;
class myException_Product_Not_Found: public exception
{
public:
virtual const char* what() const throw()
{
return "Product not found";
}
} myExcept_Prod_Not_Found;
int getProductID(int ids[], string names[], int numProducts, string target)
{
for(int i=0; i<numProducts; i++)
{
if(names[i]==target)
return ids[i];
}
try
{
throw myExcept_Prod_Not_Found;
}
catch (exception& e)
{
cout<<e.what()<<endl;
}
}
int main() //sample code to test the getProductID function
{
int productIds[]={4,5,8,10,13};
string products[]={"computer","flash drive","mouse","printer","camera"};
cout<<getProductID(productIds, products, 5, "computer")<<endl;
cout<<getProductID(productIds, products, 5, "laptop")<<endl;
cout<<getProductID(productIds, products, 5, "printer")<<endl;
return 0;
}
c++ exception

try
{
throw myExcept_Prod_Not_Found;
}
catch (exception& e)
{
cout<<e.what()<<endl;
}
You are catching the exception, essentially saying that you are handling it with the message printed to cout.
This will re-throw the exception if you wish to propagate it.
try
{
throw myExcept_Prod_Not_Found;
}
catch (exception& e)
{
cout<<e.what()<<endl;
throw;
}
If you wanted to not return 0 from your main function after you've propagated, you have to do that yourself.
int main()
{
try {
// ...
} catch (...) {
return 1;
}
return 0;
}

Your getProductID() function doesn't return from all possible execution paths. So when the function exits without a return statement, you get random garbage. This is the case when the product string isn't found.
Your try/catch block is a red herring, as it doesn't affect the remainder of the code in any way (the exception is caught immediately).
Two unrelated tips for improvement:
Catch exceptions by constant reference.
Use std::find rather than your manual loop; that way, you can write the entire function body in two lines.
Don't use C-style arrays; instead, use std::vector.

Related

Strange message (_Base_bitset::_M_do_to_ulong) getting printed out of overflow exception handler

I was trying my hands on exception handling & this code is not throwing the string it is intended to:
bitset<134> b;
b.set();
try{
if(!b.to_ulong())
throw std::overflow_error("Overflow occured\n");
}
catch(std::overflow_error& e)
{
cout<<e.what();
}
The output is:
_Base_bitset::_M_do_to_ulong
Whereas when I replace the if condition with this
if(3>2)
The expected string is printed. Whats going on in this?
What's going on: b.to_ulong(); throws std::overflow_error with its own message if the bitfield won't fit into a unsigned long before you get the chance to. The if never gets tested.
The if test is doomed anyway. It will throw the exception on any non-zero value returned by b.to_ulong(). Not what you want.
Easiest way I can think of to get your message is to catch the exception thrown by to_ulong and throwing your own.
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
bitset < 134 > b;
b.set();
try
{
b.to_ulong();
}
catch (std::overflow_error& e)
{
throw std::overflow_error("Overflow occured\n");
}
}
It might be faster to perform the testing yourself rather than calling to_ulong and dealing with two exceptions.
In your code:
bitset<134> b;
b.set(); // all bits in the set are 1's
try
{
if (!b.to_ulong()) // throws its own std::overflow_error()!
throw std::overflow_error("Overflow occured\n"); // doesn't reach.
}
catch(std::overflow_error& e)
{
cout << e.what(); // catches the exception thrown by b.to_ulong()
}

Will a try statement like this work?

Can I put just one all-encompassing try-catch statement in my main function that covers the entire program? Or do all functions require their own? What I mean is, will something like this work:
int main(){
try{
foo();
bar();
};
catch(char* e){
//Do stuff with e
};
};
void foo(){throw "You'll never reach the bar.";};
void bar(){throw "Told you so.";};
If not, is there a similar way this can be done?
Your example won't work because
Declaration of foo() and bar() are not before using them.
There is an extra semicolon between the block after try and catch.
What is passed to throw is const char*, but you catched only char*.
This example worked.
#include <iostream>
void foo();
void bar();
int main(){
try{
foo();
bar();
}
catch(const char* e){
//Do stuff with e
std::cout << e << std::endl;
}
}
void foo(){throw "You'll never reach the bar.";}
void bar(){throw "Told you so.";}
Can I put just one all-encompassing try-catch statement in my main
function that covers the entire program?
Yes. catch (...) catches everything.
#include <iostream>
int main()
{
try
{
// do something
}
catch (...)
{
std::cerr << "exception caught\n";
}
}
Or do all functions require their own?
No. That would defeat the whole purpose of exceptions.
catch(char* e){
//Do stuff with e
};
This code is a result of the misunderstanding that exceptions are error messages. Exceptions are not error messages. Exceptions in C++ can be of any type. This includes char*, of course, but it is completely unidiomatic.
What you really want to do is catch std::exception, which includes an error message, accessible via the what() member function. Well-written C++ code only throws exceptions of type std::exception or derived classes. You can add ... as a fallback for all other cases:
#include <iostream>
#include <exception>
int main()
{
try
{
// do something
}
catch (std::exception const& exc)
{
std::cerr << exc.what() << "\n";
}
catch (...)
{
std::cerr << "unknown exception caught\n";
}
}
throw "You'll never reach the bar.";
Consequently, throwing char arrays is wrong. It's wrong on a technical level if you expect a char const[] to be converted to a char*, but it's especially wrong on a design level. Replace the array with a dedicated exception type like std::runtime_error:
throw std::runtime_error("You'll never reach the bar.");

Understanding the try-block

I'm studying C++ by 2 months and I'm having some problem with understanding the try-catch block in C++. I'm using the book : programming principles and practice using C++, here is what my book says :
the basic idea of the exceptions is that if a function find is an error that it cannot handle, it does not return normally, instead, it throws an exception indicating what went wrong. Any direct or indirect caller can catch the exception, that is, specify what to do if the called code used throw.
What does "any direct or indirect caller can cacht the exception means ? does the author means the caller of a function or the catch function ?". I'm confused about this, Could you exaplain it to me in simple way ?
Example for indirect call:
Here the exception happens in the called function. But the try catch is placed in the calling function, and not the called function.
#include <iostream>
#include <exception>
using namespace std;
void divideByZero(){
int a = 5;
int b = a / 0;
throw(b);
}
int main()
{
try{
divideByZero();
}
catch (exception& e){
cout<<e.what()<<endl;
}
return 0;
}
Example for direct exception:
Here the exception happens in the functions itself directly, and handled there itself.
#include <iostream>
using namespace std;
int main()
{
try{
int a = 5;
int b = a / 0;
throw(b);
}
catch (exception& e){
cout<<e.what()<<endl;
}
return 0;
}
The above program is used only for illustration and not for any real example, which you are likely to come across when you write a useful program.

C++ get description of an exception caught in catch(...) block

can I get description of an exception caught by
catch(...)
block? something like .what() of std::exception.
There is one trick you might be able to use:
catch(...) {
handle_exception();
}
void handle_exception() {
try {
throw;
} catch (const std::exception &e) {
std::cout << e.what() << "\n";
} catch (const int i) {
std::cout << i << "\n";
} catch (const long l) {
std::cout << l << "\n";
} catch (const char *p) {
std::cout << p << "\n";
} catch (...) {
std::cout << "nope, sorry, I really have no clue what that is\n";
}
}
and so on, for as many different types as you think might be thrown. If you really know nothing about what might be thrown then even that second-to-last one is wrong, because somebody might throw a char* that doesn't point to a nul-terminated string.
It's generally a bad idea to throw anything that isn't a std::exception or derived class. The reason std::exception exists is to allow everybody to throw and catch objects that they can do something useful with. In a toy program where you just want to get out of there and can't even be bothered to include a standard header, OK, maybe throw an int or a string literal. I don't think I'd make that part of a formal interface. Any exceptions you throw are part of your formal interface, even if you somehow forgot to document them.
That block might catch an int, or a const char*, or anything. How can the compiler possibly know how to describe something when it knows nothing about it? If you want to get information off an exception, you must know the type.
If you know you only throw std::exception or subclasses, try
catch(std::exception& e) {...e.what()... }
Otherwise, as DeadMG wrote, since you can throw (almost) everything, you cannot assume anything about what you caught.
Normally catch(...) should only be used as the last defense when using badly written or documented external libraries. So you would use an hierarchy
catch(my::specialException& e) {
// I know what happened and can handle it
... handle special case
}
catch(my::otherSpecialException& e) {
// I know what happened and can handle it
... handle other special case
}
catch(std::exception& e) {
//I can at least do something with it
logger.out(e.what());
}
catch(...) {
// something happened that should not have
logger.out("oops");
}
Since C++11 you can capture the current exception with a pointer:
std::exception_ptr p; // default initialization is to nullptr
try {
throw 7;
}
catch(...)
{
p = std::current_exception();
}
This behaves like a smart pointer; so long as there is at least one pointer pointing to the exception object it is not destroyed.
Later (maybe even in a different function) you can take action in a similar way to the current top answer:
try {
if ( p )
std::rethrow_exception(p);
}
catch(int x)
{
}
catch(std::exception &y)
{
}
How we have our exceptions implemented is that, we have our own Exception classes, that are all derived from std::exception..
Our exceptions will contain Exception message, Function name, File name and line where exceptions are generated. These are all useful not just to show the Messages but also can be used for logging which helps to diagnose the Exception quite easily. So, we get the entire information about the Exceptions generated.
Remember exceptions are for us to get information about what went wrong. So, every bit of information helps in this regard..
Quoting bobah
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}

Is there any way to get some information at least for catch(...)?

Is there any way to get at least some information inside of here?
...
catch(...)
{
std::cerr << "Unhandled exception" << std::endl;
}
I have this as a last resort around all my code. Would it be better to let it crash, because then I at least could get a crash report?
No, there isn't any way. Try making all your exception classes derive from one single class, like std::exception, and then catch that one.
You could rethrow in a nested try, though, in an attempt to figure out the type. But then you could aswell use a previous catch clause (and ... only as fall-back).
You can do this using gdb or another debugger. Tell the debugger to stop when any exception is throw (in gdb the command is hilariously catch throw). Then you will see not only the type of the exception, but where exactly it is coming from.
Another idea is to comment out the catch (...) and let your runtime terminate your application and hopefully tell you more about the exception.
Once you figure out what the exception is, you should try to replace or augment it with something that does derive from std::exception. Having to catch (...) at all is not great.
If you use GCC or Clang you can also try __cxa_current_exception_type()->name() to get the name of the current exception type.
Yes there is, but how useful it is is open to debate:
#include <exception>
#include <iostream>
using namespace std;
int f() {
throw "message";
}
int main() {
try {
f();
}
catch ( ... ) {
try {
throw;
}
catch( const char * s ) {
cout << "caught " << s << endl;
}
}
}
And to actually to answer your question, IMHO you should always have a catch(...) at
the top level of your code, that terminates (or otherwise handles) when presented with an unexpected exception in your application, in a manner fully documented by your application's manual.
I believe you should catch (...), if you have a reasonable course of action at that point and want the application to keep running.
You don't have to crash in order to generate a crash report, mind you. There's API for generating a mini-dump and you can do it in your SEH handler.
here's an approach I used on one project. it involves rethrowing until an exception type is matched against a list of known exceptions and then dispatching some action upon a match (in this case just returning some string information, but it could also be calling a registered function object).
This idea can be extended into a dynamic registry of exception types if you wish, the thing you have to be careful of is to ensure that the list is in most-derived to least-derived order (requires a lot of rethrowing and catching during registration!)
#include <iostream>
#include <stdexcept>
#include <exception>
#include <typeinfo>
#include <system_error>
namespace detail {
// a function which compares the current exception against a list of exception types terminated
// with a void type
// if a match is made, return the exception (mangled) class name and the what() string.
// note that base classes will be caught if the actual class is not mentioned in the list
// and the list must be in the order of most-derived to least derived
//
template<class E, class...Rest>
std::string catcher_impl()
{
try
{
std::rethrow_exception(std::current_exception());
}
catch(const E& e)
{
bool is_exact = typeid(E) == typeid(e);
return std::string(typeid(E).name()) + (is_exact ? "(exact)" : "(base class)") + " : " + e.what();
}
catch(...)
{
return catcher_impl<Rest...>();
}
return "unknown";
}
// specialise for end of list condition
template<> std::string catcher_impl<void>()
{
return "unknown exception";
}
}
// catcher interface
template<class...Es>
std::string catcher()
{
return detail::catcher_impl<Es..., void>();
}
// throw some exception type
// and then attempt to identify it using the type list available
//
template<class E>
void test(E&& ex)
{
try
{
throw std::forward<E>(ex);
}
catch(...)
{
std::cout << "exception is: "
<< catcher<std::invalid_argument, std::system_error, std::runtime_error, std::logic_error>()
<< std::endl;
}
}
int main()
{
test(std::runtime_error("hello world"));
test(std::logic_error("my logic error"));
test(std::system_error(std::make_error_code(std::errc::filename_too_long)));
test(std::invalid_argument("i don't like arguments"));
struct my_runtime_error : std::runtime_error
{
using std::runtime_error::runtime_error;
};
test(my_runtime_error("an unlisted error"));
}
example output:
exception is: St13runtime_error(exact) : hello world
exception is: St11logic_error(exact) : my logic error
exception is: NSt3__112system_errorE(exact) : File name too long
exception is: St16invalid_argument(exact) : i don't like arguments
exception is: St13runtime_error(base class) : an unlisted error