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).
Related
I have a matrixType File that works fine, but I am now trying to replace the if statements with the try, catch, and throw statements within a function of a class. I am just trying to understand one function so I can apply it to the others. Since I did try to do the try and catch statements but it skipped over the try statement and caused an actual exception that stops the program completely.
The One function I am focusing on is the equal operator
Here is the HeaderFile
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
class matrixType
{
private:
int **matrix;
int row;
int col;
public:
const matrixType& operator=(const matrixType& mat);
}
Here is the class.cpp file that currently works
#include "matrixType.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdexcept>
#include <limits>
using namespace std;
const matrixType& matrixType::operator=(const matrixType& mat)
{
if (row != mat.row || col != mat.col)
{
cout << "The matrixes are not identical" << endl;
return *this;
}
for (int i = 0; i < row; i++)
{
for (int r = 0; r < col; r++)
{
matrix[i][r] = mat.matrix[i][r];
}
}
return *this;
}
Then this is the source file
#include <iostream>
#include <string>
#include <stdexcept>
#include <limits>
#include "matrixType.h"
using namespace std;
int main()
{
matrixType test1(3, 3);
matrixType test2(2, 2);
test1 = test2;
return 0;
}
So the big question is how do you throw an exception
I tried
Try
{
if(mat.row != row || mat.col != col)
throw exception("The matrixes are not identical")
}
catch (exception & e)
{
cout << e.what << endl;
}
Which caused the actual exception to pop up but when I leave the if statement it works and does not go into a fail state. Does anyone see what I was doing wrong if I replaced the if statement with the code above?
First, a note about the meaning of exceptions. Further down, I'll address what's wrong with your code.
The meaning of throwing an exception in C++, in English, is roughly, "I can't deal with this situation anymore, I'm giving up right now, and I'm hoping that somebody else can deal with this." The meaning of catching an exception is roughly, "oops, somebody screwed up, but I'm going to do something about it now." With this in mind, let's look at how this works in more concrete detail.
Many functions have preconditions, which are things that function always expects to be true before it runs. For example, a squareRoot(double x) function might have a precondition that x must never be negative. When a function's precondition is violated, it's a natural time for that function to say "I'm giving up right now, deal with it!" since somebody who called that function is doing something wrong, and squareRoot can't possibly fix that. This could look like the following:
// precondition: x must not be negative
double squareRoot(double x){
if (x < 0.0){
// precondition is violated
throw std::runtime_error("input to squareRoot was negative");
// the function exits here!
// this point in code is not reachable
}
// otherwise, precondition is satisfied, it's safe to continue
...
return result;
}
elsewhere, in the wild:
void myFunction(){
double x;
cout << "x = ";
cin >> x;
double y = squareRoot(x);
cout << ", y = " << y << '\n';
}
Here, if somebody types in a negative number, then the preconditions of squareRoot are violated, and it throws an exception. This means that squareRoot will not return normally, and neither will myFunction. When exception is thrown, everything is interrupted until you catch the exception, which can happen far outside the current function.
int main(){
try {
myFunction(); // this might throw
// if myFunction() throws, the following output will not happen!
cout << "Thanks! have a nice day.\n";
} catch (std::runtime_error e) {
// if myFunction() does throw, the error lands right here
cout << "Oops! an error occurred: " << e.what() << '\n';
}
return 0;
}
It's important to note that you should only throw exceptions when something is really wrong. Exceptions are not a replacement for ordinary program logic, and they're not a replacement for validating things like user input.
About custom classes:
When you're defining a custom class type, if it has either a copy constructor, copy assignment operator, or destructor, that probably means that your class has sensitive information that needs special care to clean up and keep track of. If you've written at least one of these functions, you should implement all three of them. Otherwise, it's extremely easy to introduce memory leaks, false data sharing, and all kinds of unwanted Undefined Behavior into your program.
About your copy assignment operator:
The purpose of a copy assignment operator, as in a = b; is that after it runs, the left-hand object should be logically identical to the right-hand object, and the right-hand object should not have changed. The previous state of the left-hand object is lost at this point. What exactly logically identical means is a question of what your class is representing.
In the case a simple matrix, I would expect two matrices to be identical when they have the same width, height, and values for all elements, and I would implement a copy assignment operator accordingly. For example:
Matrix& Matrix::operator=(const Matrix& other){
releaseMemory(); // clean up old data
resize(other.rows, other.cols); // allocate new data
for (int i = 0; i < rows; ++i){
for (int j = 0; j < cols; ++j){
this->data[i][j] = other.data[i][j]; // copy each value
}
}
return *this;
}
I leave the implementation of the details to you. You should be able to find great examples and detailed explanations of how to overload operators, write your own copy constructor and destructor, and about good practice in general by reading a good C++ book.
Actually, I figured it out I have to use return statements as it worked when I included a return statement within the catch function.
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()
}
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.
int main()
{
int *a; // a = 0x4053c6 (a random address)
// this will cause the program to exit, and how do i know this memory can't be written ?
*a = 5;
return 0;
}
Confused! I mean does this snippet always lead the program to crash ? And is there a case that this program can execute from begin to end?
It will usually lead to a crash, but it's not guaranteed (since the variable is uninitialized, it could contain any value, valid or invalid). You can't catch an access violation with C++ exceptions, but compilers provide extensions to do it. For example, with Visual C++, you can use SEH (Structured Exception Handling):
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
int* p = reinterpret_cast<int*>(0x00000100);
__try
{
*p = 10;
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
cout << "Access violation" << endl;
return -1;
}
cout << *p << endl;
}
The code will Segfault / have an access violation which is handled as a trap or a signal depending on the operating system. You may be able to handle it but it is quite unlikely you'll be able to do much afterward. (The usual course of action after handling it is a graceful exit).
As for establishing that there is a case it will be quite tough to prove it. You can have your own compiler that sets uninitialized variables to a particular address on the stack for example (sarcasm).
One way to pseudo-initialize the value in a is to call a function:
void func(int k)
{
int *a;
int b = 0;
if (k == 1) {
a = &b;
}
*a = 5;
}
You can try with func(1) a few times and then try func(2). There is a chance that a and b will reuse the same stack area and not fail. But again this is also a chance.
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;
}