Understanding the try-block - c++

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.

Related

Pretty confused about C++ Exception Handling

Trying to add exception handling to my C++ program, but I find it pretty confusing. The program sets the values i and j to their highest possible values and increments them. I think I want the exception handling to detect the integer overflow / wraparound when it happens(?)
So far this is what I've got:
#include <iostream>
#include <limits.h>
#include <exception>
#include <stdexcept>
using namespace std;
int main() {
int i;
unsigned int j;
try{
i = INT_MAX;
i++;
cout<<i;
}
catch( const std::exception& e){
cout<<"Exception Error!";
}
try{
j = UINT_MAX;
j++;
cout<<j;
}
catch(const std::exception& e){
cout<<"Exception Error!";
}
}
The program runs, but the exception handling part doesn't work.
What could be the issue?
Well the behaviour of incrementing i beyond INT_MAX is undefined. That's because it's a signed integral type. I've never come across an implementation that throws an exception in this case. (Typical behaviour is wrap-around to INT_MIN but don't rely on that.)
Incrementing j beyond UINT_MAX must wrap-around to 0. That's because it's an unsigned type. That is, an exception must never be thrown.
C++ does not define any exceptions to be thrown in case of integer overflow. If you want to achive such behavior you will need some wrapper for integer class with corresponding functionality, such as Safe Int library. Example:
#include <safeint.h>
#include <iostream>
int main()
{
try
{
::msl::utilities::SafeInt<int> j;
for(;;)
{
++j;
}
}
catch(::msl::utilities::SafeIntException const & exception)
{
switch(exception.m_code)
{
case ::msl::utilities::SafeIntArithmeticOverflow:
{
::std::cout << "overflow detected" << ::std::endl;
break;
}
default:
{
break;
}
}
}
return(0);
}
In C++, exceptions don’t just happen. Exceptions are thrown by the throw keyword; if your code (or code you’ve linked to) doesn’t have throw something() it doesn’t throw exceptions.
That’s not quite true, however: there are funky situations where the code does something inappropriate (formally, the code has undefined behavior), which might result in an exception being thrown. That’s outside the rules of the language definition, so not portable and not reliable (yes, I’m looking at you, Windows SEH).

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

exception handling

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.

exception handling a constructor

This was an interview question of me.
Surprisingly i never thought of this kinda question to myself.
can we have exception handling inside a constructor c++?
in tense and not thinking much i said "yes we could probably do it in a constructor.lets say we are allocating some memory using new operator to a pointer member and it throws a bad alloc exception,in this way there is a possibility of exceptions being raised"
Then later i thought that constructors can never return a value.So how can an exception inside a constructor caught.now i am asking this to myself!
can anybody pls help me to come out of this confusion?
See this GOTW Constructor Failures question which addresses your query somewhat and goes on to say it is a waste of time.
Constructors don't have a return type,
so it's not possible to use return
codes. The best way to signal
constructor failure is therefore to
throw an exception. If you don't have
the option of using exceptions, the
"least bad" work-around is to put the
object into a "zombie" state by
setting an internal status bit so the
object acts sort of like it's dead
even though it is technically still
alive.
You would catch the exception in the calling code, not within the constructor.
See How can I handle a constructor that fails? for further details (actually, I'd suggest reading the whole page about exception handling, truly enlightening).
Exception handling and return type are completely different. when the program find the exception in constructor, it throws the exception to nearly by catch block [if used] or thrown to caller (main()). in this case, we have catch block in constructor and exception handled by it. Once exception handled, the remaining statement in the constructor/function will be started executing. see the below example,
class A
{
public:
A(){
printf("Hi Constructor of A\n");
try
{
throw 10;
}
catch(...)
{
printf("the String is unexpected one in constructor\n");
}
printf("Hi Constructor of A\n");
}
~A(){
printf("Hi destructor of A\n");
}
};
int main()
{
try{
A obj ;
throw "Bad allocation";
}
catch(int i)
{
printf("the Exception if Integer is = %d\n", i);
}
catch(double i)
{
printf("the Exception if double is = %f\n", i);
}
catch(A *objE)
{
printf("the Exception if Object \n");
}
catch(...)
{
printf("the Exception if character/string \n");
}
printf("Code ends\n");
return 0;
}
This produce Output:
Start: Constructor of A
the String is unexpected one in constructor
End: Constructor of A
Hi destructor of A
the Exception if character/string
Code ends
C++ has try-catch clauses similar to those of other languages. A tutorial can be found online: http://www.cplusplus.com/doc/tutorial/exceptions/
EDIT: example turned into fully working code
#include <iostream>
using namespace std;
class A
{
public:
void f(){
throw 10;
}
A(){
try{
f();
}
catch(int e){
cout << "Exception caught\n";
}
}
};
int main (int argc, const char * argv[])
{
A a;
return 0;
}
This produces output:
Exception caught

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