Not understanding errors and try{} catch{}

My task was to create program that would test whats the biggest Fibonacci number thats fits in int
(Next number is sum of 2 previous numbers) 1 1 2 3 5 8 13 21 34 55 ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>
using namespace std;

int main(){

	vector<int> vec;
	try{
		int previous1 = 1,previous2 = 0, next=1;
		while (next){
			next = previous1 + previous2;
			vec.push_back(next);
			previous1 = next;
			previous2 = previous1;

		}
	}
	catch (...){
		cout << "The biggest Fibonacci number that fits in int is " << vec[vec.size()-1];
	}
	system("pause");

}


I was thinking that when i reach the number that doesnt fit in int ill get some error message and than i can catch that and just display the last valid int in my vector. Instead program just instantly ends and i have to "press anything to continue . . ."

So my question is why is this happening that i dont get errors and how could this be build without using a vector (not that my vector worked anyway)?
catch will only catch something if you throw it. You are not throwing anything in your code, so there is nothing to catch.

If you want to throw an error when the 'next' variable overflows, you will have to detect the overflow yourself and throw the error:

1
2
3
next = previous1 + previous2;
if(next < previous1)
    throw overflow_error();  // #include <stdexcept> for overflow_error 


EDIT:

FWIW this is not a practical use of exceptions, and I wouldn't recommend using them like this in actual programs.
Last edited on
A simple cout added for debugging reveals a couple of problems:
 
cout << "P1=" << previous1 << " P2=" << previous2 << " N=" << next << endl;


1) You're calculating powers of 2, not Fibonacci numbers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
P1=1 P2=0 N=1
P1=1 P2=1 N=2
P1=2 P2=2 N=4
P1=4 P2=4 N=8
P1=8 P2=8 N=16
P1=16 P2=16 N=32
P1=32 P2=32 N=64
P1=64 P2=64 N=128
P1=128 P2=128 N=256
P1=256 P2=256 N=512
P1=512 P2=512 N=1024
P1=1024 P2=1024 N=2048
P1=2048 P2=2048 N=4096
P1=4096 P2=4096 N=8192
P1=8192 P2=8192 N=16384
P1=16384 P2=16384 N=32768
P1=32768 P2=32768 N=65536
P1=65536 P2=65536 N=131072
P1=131072 P2=131072 N=262144
P1=262144 P2=262144 N=524288
P1=524288 P2=524288 N=1048576
P1=1048576 P2=1048576 N=2097152
P1=2097152 P2=2097152 N=4194304
P1=4194304 P2=4194304 N=8388608
P1=8388608 P2=8388608 N=16777216
P1=16777216 P2=16777216 N=33554432
P1=33554432 P2=33554432 N=67108864
P1=67108864 P2=67108864 N=134217728
P1=134217728 P2=134217728 N=268435456
P1=268435456 P2=268435456 N=536870912
P1=536870912 P2=536870912 N=1073741824
P1=1073741824 P2=1073741824 N=-2147483648
P1=-2147483648 P2=-2147483648 N=0
33 numbers pushed


2) Note that at iteration 32, N goes negative. In iteration 33, N becomes 0, which terminates your while loop. You fell through the try block. No exception was raised.

You could build this with a simple array, but you would need to know the maximum number of entries in advance. std::vector is a good choice for this problem.
Last edited on
Tnx a lot guys for responses. This worked well.
Side question : Buy what if i use range error while working with vector and this vector is in try{} block, than something in vector library would throw exception right? Than i can catch it with catch{} right?

FWIW this is not a practical use of exceptions, and I wouldn't recommend using them like this in actual programs.

Also could someone tell me why isnt this good use. I just started reading "Bjarne Stroustrup: Programming -- Principles and Practice Using C++" and i just saw exceptions when he introduced them for the 1st time in my life. He told he will talk later on more about them so im not that good with them right now.

Also - i was thinking that i can probably throw anything instead of overflow_error("...") right? Like make emty class like class Overflow{}; and throw Overflow(); Would that make a difference (maybe 1 is safer than another?)

I saw in this book that stuff like this class Overflow{}; and throw Overflow(); could work (just checked out - it works) but Overflow() is like type of the object not an object itself. Shouldn't we at 1st make this object like Overflow error(); And than thow this object when its created? If someone have some free time would apprecciate answer to this a lot
Last edited on
Side question : Buy what if i use range error while working with vector and this vector is in try{} block, than something in vector library would throw exception right? Than i can catch it with catch{} right?


If vector throws something, yes you can catch it in your catch block.

vector will throw a 'bad_alloc' exception if it fails to allocate memory, and vector::at will also throw an 'out_of_range' exception if you attempt to access an out of range element.

However accessing elements via the [] operator, and even via iterators will not throw any exception.

Also could someone tell me why isnt this good use


You're basically only using it to escape a loop. It'd be better if you just made the 'exception' case the loop condition.

Exceptions should not be used as just a way to jump to another part of code. They're to be used when something has failed miserably.

In your case, nothing has failed. You simply reached the end of what you were trying to do. So exceptions are inappropriate here.


Also - i was thinking that i can probably throw anything instead of overflow_error("...") right? Like make emty class like class Overflow{}; and throw Overflow(); Would that make a difference (maybe 1 is safer than another?)


You are correct. You can throw anything you want.

Though I find it's best to stick with standard exception classes where possible. For the same reason it's best to stick with standard container classes where possible: everyone is familiar with them and they're a common ground for all programmers.

Best of all, all standard exception classes are inherited from the std::exception base class, so this will catch practically every exception that could be thrown, AND it will tell you what went wrong:

1
2
3
4
5
try{  ...  }
catch( std::exception& e )
{
    cout << "This is what went wrong: " << e.what();
}


Child classes like overflow_error are further specialized so that you can have multiple catch block to handle different failure scenarios:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try{  ...  }
catch( std::overflow_error& e )
{
    // had an overflow error
}
catch( std::bad_alloc& e )
{
    // was unable to allocate enough memory
}
catch( std::out_of_range& e )
{
    // tried to access something out of range
}
catch( std::exception& e )
{
    // something else went wrong
}



As you might be able to see here, std::exception acts as a "catch all"... similar to the ellipsis: catch(...). The difference is, the ellipsis does not give you any information about what was thrown, whereas with the std::exception class, you have an actual object that you can probe for information.



So yeah, my advice: either use the standard exception classes directly... or derive your own exception classes from them. Don't throw anything that doesn't ultimately derive from std::exception. Even though the language allows it, it isn't a good idea.
Wow tnx a lot, Disch. This was very well explained. I feel like understanding it all already :)
Topic archived. No new replies allowed.