std::out_of_range exception is not thrown - c++

// The following code works fine, throwing a std::out_of_range exception:
std::vector<double> vd{ 1.5 };
try {
int i{ -1 };
double d = vd.at(i); // exception is thrown
}
catch (std::out_of_range& re) {
std::cout << "Exception is " << re.what() << std::endl; // invalid vector subscript
}
If I access vector elements in a for loop with an invalid index, no std::exception is thrown although I use .at(). Why is the std::out_of_range exception not thrown?
// in a for loop, this does not throw the exception!
std::vector<double> vd{ 1.5 };
try {
for (int i = -1; i < vd.size(); ++i)
double d = vd.at(i); // exception is not thrown. Why?
}
catch (std::out_of_range& re) {
std::cout << "Exception is " << re.what() << std::endl; // exception is not thrown
}

Because the loop does not execute. -1 < vd.size() is false.
size() returns an unsigned value. So before comparing the two numbers -1 is converted into an unsigned value. This conversion is done modulo the largest unsigned value plus one, which means that -1 is converted to the largest possible unsigned value. That is then compared with the size of your vector, and that comparison is always false.
Signed/unsigned comparsions are problematic for this reason. Although well defined, they don't work in the mathematically expected way if the signed value is negative. Your compiler should warn you about this problem.

Related

Does "try-catch" catches run time error (especially Out of Range error)

I'm following an example code from Programming Principles and Practice Using C++ in one of the example for exception it shows this snippet of code
int main()
{
try {
vector<int> v; // a vector of ints
for (int x; cin >> x; )
v.push_back(x); // set values
for (int i = 0; i <= v.size(); ++i) // print values
cout << "v[" << i << "] == " << v[i] << '\n';
}
catch (const out_of_range& e) {
cerr << "Oops! Range error\n";
return 1;
}
catch (...) { // catch all other exceptions
cerr << "Exception: something went wrong\n";
return 2;
}
}
From what I understand it is suppose to catch out_of_range error and output "Oops! Range error". However, the Visual Studio 2019 shows this instead.
can someone explain why it shows me this
Does “try-catch” catches run time error (especially Out of Range error)?
No, in C++ most run time errors lead to Undefined Behavior, not exceptions. Only errors which explicitly throw exceptions can be caught.
std::vector<T>::operator[] does not specify that it throws an exception when you access out of bounds, it is just Undefined Behavior and anything can happen. It can even appear to work. When I try it here, there isn't any visible error : https://godbolt.org/z/Pcv9Gn8M9
If you want an exception on out of bounds access, std::vector<T>::at() does throw std::out_of_range.
For your test you should use v.at(i) instead of v[i]. Try it here : https://godbolt.org/z/szKxhjxhx.

Exception: wrong output

int At(int i, int j) const {
try {
if (i >= m.size() || j >= m[0].size())
throw out_of_range("out_of_range");
return m.at(i).at(j);
}
catch (exception& e) {
cout << e.what() << endl;
}
}
int& At(int i, int j) {
try {
if (i >= m.size() || j >= m[0].size())
throw out_of_range("out_of_range");
return m.at(i).at(j);
}
catch (exception& e) {
cout << e.what() << endl;
}
}
int main() {
Matrix one, two(2, 3);
cout << two;
one.Reset(0, 0);
cout << one.At(4, 4);
return 0;
}
in this code must be printed exception: out_of_range, but in my case it is :
out_of_range
-244281
What are this number and how can I remove it from output?
If the exception is thrown, then the catch handler prints the message ("out_of_range") and then the function continues on like nothing happened.
The problem is that this "continue on" leads to the functions ending without you returning anything, leading to undefined behavior when you try to print this non-return value.
If you declare a function to return anything, the you must return something.
With that said, catching the exception in the At function makes no sense. And considering that one of the variants return a reference, it's very hard to return a "value" since you can't have "null" references.
The solution then is not to have the try-catch at all in the functions, but let the caller of the function handle any possible exception.
int& At(int i, int j) {
// ...
catch (exception& e) {
cout << e.what() << endl;
}
}
The exception is caught and printed ...and then At() returns normally.
Your compiler should've warned you about returning from a non-void function without returning a value.
In your main():
cout << one.At(4, 4);
So, now this attempts to interpreted the value returned from At() as a reference to some int. Nothing was returned, so this is undefined behavior, and you can get any random junk printed here. Or your program can crash. You have no logical expectations, any more.

pre & post condition usage. Why isn't the program responding to conditions

int mult (int a, int b)
{
if (a <= 0 || b <= 0) throw (" Your input is invalid. No zero");
int doub = a * b;
if (doub <= 0) throw (" Invalid value");
cout << "\\n" << doub;
return doub;
}
//code that gives values of num1 & num2//
try
{
mult(num1, num2);
}
catch (int error)
{
cerr << " Error ###$% invalid value";
}
The program works fine if both values (num1, numa2) are higher than 0, but if any value is less than 0 the program fails and doesn't throw the desired message. It just shows a default error.
Is it inproper use of the pre & post condition?
Is it the throw usage? (I have some doubts in how to use it, it might be that but I don't know)
throw (" Your input is invalid. No zero"); You are throwing a char *
catch (int error) But you are catching an int. This is a different type from char * so the exception is not caught and propagates up to the default handler.
The idiomatic way to do handle this would be to throw (std::runtime_error("Your input is invalid. No zero"));,
and catch (std::exception & e) { cerr << e.what(); }
You are throwing exceptions of type const char * but catching them as type int. To fix this, all you need to do is change:
catch (int error)
to:
catch (const char * error)
Live demo
Or, as QuestionC says, you can throw a std::runtime_error and catch that.

C++ exception not handling as expected

I'm trying to throw an exception in my code if a vector that is created from user input is not sorted in either descending or ascending order.
using namespace std;
#include <iostream>
#include <vector>
#include <algorithm>
int main () {
vector <int> vec;
//Let user fill a vector with 12 integers.
//cout << "Please note that input data should be either increasing or decreasing." << endl;
int n = 0;
int size = 0;
while(size < 12) {
cout << "Type integer to add to the vector." << endl;
cin >> n;
vec.push_back(n);
++size;
}
//throw exception if unsorted
try {
if (!((is_sorted(vec.begin(), vec.end())) || (is_sorted(vec.end(), vec.begin())))) {
throw "Input was not sorted.";
}
}
catch(exception &error){
cerr << "Error: " << error.what() << endl;
}
}
I have not included the rest of the code, which searches for a particular number, because I am pretty sure that it is irrelevant to this issue. When the data filled into the vector is ascending or descending, everything is fine, but when I test the exception, I get, "terminate called after throwing an instance of 'char const*' Aborted" instead of my desired error message. I don't understand what is going on here. Is it something wrong with the way I'm handling exceptions or am I using the sort() function incorrectly?
In C++, all types are throwable and catchable, but you are only catching subclasses of std::exception.
The best fix to your code would be changing your throw statement to:
throw std::runtime_error("Input was not sorted.");
If you want to catch an exception, you should throw an exception, not a const char*.
See this answer: c++ exception : throwing std::string
You're throwing a const char* not an std::exception. So catch it as a const char*:
catch(const char* error) {
std::cout << "Error: " << error << "\n";
}
Or throw an std::exception.
Remember that you can throw many types and have many catch blocks, the one that will be invoked is the one that matches the type of the thrown exception.

No output while doing try catch in c++

I am trying to catch bad allocation error. When input length will be in order of 10000000000000000000000 or something, then bad allocation error should come. I don't know why its not being caught.
Any help will be appreciated!
# include <vector>
# include <iostream>
using namespace std;
void length(int m)
{
vector<int> x;
try
{
x.resize(m);
}
catch(std::bad_alloc&)
{
cout << "caught bad alloc exception" << std::endl;
}
}
int main()
{
int l;
cout << "Length" ;
cin >> l ;
length(l);
return 0;
}
UPDATED:
When I am hard coding the value for input, then it is throwing an exception. I don't know why its working this way.
# include <vector>
# include <iostream>
using namespace std;
void length(int m)
{
vector<int> x;
try
{
x.resize(m);
}
catch(std::bad_alloc&)
{
cout << "caught bad alloc exception" << std::endl;
}
}
int main()
{
int m= 100000000000000000000;
length(m);
return 0;
}
You ought to write
if (!(cin >> l)){
// I could not read that into `l`
}
The lack of an exception being caught could be down to
Your int value being smaller than you think (perhaps some undefined wrap-around behaviour), and an exception is not thrown since the allocation is successful.
The allocation being lazy in the sense that the memory is not allocated until you actually use it.
If std::bad_alloc is thrown as an anonymous temporary then it will not be caught at your catch site. (Unless your naughty compiler allows non-const references to bind to anonymous temporaries, which some do as an extension). Write catch (const std::bad_alloc&) instead, and it will be caught there.
The maximum length of an integer type int is 2.147.483.647 . Are you sure you have actually used an higher number to test it?
You're passing Integer variable which has the limit.
Minimum value for a variable of type short: –32768
Maximum value for a variable of type short: 32767
The error which you will get from your code is std::length_error
To raise the bad allocation error dynamically you can try malloc() with incorrect size OR try below code.
#include <iostream>
#include <new>
int main()
{
try {
while (true) {
new int[100000000ul];
}
} catch (const std::bad_alloc& e) {
std::cout << "Allocation failed: " << e.what() << '\n';
}
}
</i>
No exception is thrown because the int that makes it through to your function void length(int m) is capped at its max value that is much less than vector::max_size(). Consider:
void length(int m)
{
cout << "m is: " << m << " which has a max value: " << numeric_limits<int>::max() << endl;
// ...
}
with the output:
Length10000000000000000000000
m is: 2147483647 and has a max value: 2147483647