#include <iostream>
#include <array>
#include <exception>
using namespace std;
template<class T, int N>
void PrintArray(array<T, N> a)
{
for (int i = 0; i < int(a.size()); i++)
{
cout << a[i] << ' '; a[i] = 1 + i;
}
}
int main()
{
array <int, 6> arr = { 1,2,3,4,5,6 };
PrintArray<int, 6>(arr);
cout << "2a pos do arr -> ";
cout << arr[2] << endl;
**cout << arr[7] << endl;**
system("Pause");
return 0;
}
I don't seem to be understanding how to use try catch to handle this exception, or if it is even possible (I believe it is). Can someone please explain how would I handle the non existent element of the array.
Accessing an array out of bounds (whether it is a std::array or a C-style array) using the [] operator is undefined behavior, there is no bounds checking performed, so there is no guarantee of an exception being thrown at all. Best case, an OS exception will be thrown, which you may or may not be able to catch. Worse case, no exception will be thrown at all and you will corrupt memory, which you may or may not notice for a long time if ever.
If you want to guarantee a standardized catchable exception is thrown, use the std::array::at() method, which throws a std::out_of_range exception that you can catch with a standard C++ try/catch block, eg:
#include <iostream>
#include <array>
#include <exception>
#include <cstdlib>
template<class T, int N>
void PrintArray(std::array<T, N> &a)
{
for (size_t i = 0; i < a.size(); ++i)
{
std::cout << a[i] << ' '; a[i] = 1 + i;
}
}
int main()
{
std::array <int, 6> arr = { 1,2,3,4,5,6 };
PrintArray(arr);
std::cout << "2a pos do arr -> ";
std::cout << arr[2] << std::endl;
try {
std::cout << arr.at(7) << std::endl;
}
catch (const std::out_of_range &) {
std::cout << "range error!" << std::endl;
}
std::system("Pause");
return 0;
}
If you try to access an array index which is out of bounds your program will crash - you can't catch that. You just need to guard against it to make sure it cannot happen
EDIT - Of course the replies to this answer are valid, it is not guaranteed to crash. You may even be lucky and get an exception but that's unlikely so no point in trying to handle it.
BUT I stand by the answer - make sure it cannot happen. Theres so many ways to do this, runtime checks, use std::array and at() (with try/catch), ASSERTS the options are endless. It's much better to avoid situations happening through good design than to handle the situation when it has already happened.
Related
I use std::erase_if to erase half the elements from containers using a captured counter as follows. C++20 compiled with gcc10
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
int main()
{
{
std::vector<int> container(10);
std::cout << container.size() << std::endl;
std::erase_if(container, [i = 0u](auto&&...) mutable { return i++ % 2 == 0; });
std::cout << container.size() << std::endl;
}
std::cout << std::endl;
{
std::map<int, int> container;
for (int i = 0; i < 10; i++) {
container.emplace(i, i);
}
std::cout << container.size() << std::endl;
std::erase_if(container, [i = 0u](auto&&...) mutable { return i++ % 2 == 0; });
std::cout << container.size() << std::endl;
}
std::cout << std::endl;
{
std::unordered_map<int, int> container;
for (int i = 0; i < 10; i++) {
container.emplace(i, i);
}
std::cout << container.size() << std::endl;
std::erase_if(container, [i = 0u](auto&&...) mutable { return i++ % 2 == 0; });
std::cout << container.size() << std::endl;
}
}
The output is unexpected. For vector, an extra element is removed:
10
4
10
5
10
5
I print out the result and it seems like vector[1] is the unexpectedly removed element
Granted that this is not usually a normal usage for erase_if but I'm still curious why it happens only for vector but not for the other map. I'd guess it has something to do with the iterator type shenanigan. Appreciate if someone could give a detailed explanation.
remove_if takes a Predicate. And the standard library requires that a Predicate type:
Given a glvalue u of type (possibly const) T that designates the same object as *first, pred(u) shall be a valid expression that is equal to pred(*first).
Your predicate changes its internal state. As such, calling it twice with the same element will yield different results. That means it does not fulfill the requirements of Predicate.
And therefore, undefined behavior ensues.
This question already has answers here:
Vector going out of bounds without giving error
(4 answers)
Closed 5 years ago.
I read this tutorial
std::vector beginners tutorial
and also saw this question:
similar tpoic question
Yet, when I run my simple example I did not see the excepted results, which are --> an std::out_of_range exception is NOT thrown.
Did I misunderstand here something ?
The sample code I run is the following (the code run and terminates successfully, i.e.- no exceptions thrown):
#include <iostream>
#include <vector>
using namespace std;
class MyObjNoDefualtCtor
{
public:
MyObjNoDefualtCtor(int a) : m_a(a)
{
cout << "MyObjNoDefualtCtor::MyObjNoDefualtCtor - setting m_a to:" << m_a << endl;
}
MyObjNoDefualtCtor(const MyObjNoDefualtCtor& other) : m_a(other.m_a)
{
cout << "MyObjNoDefualtCtor::copy_ctor - setting m_a to:" << m_a << endl;
}
~MyObjNoDefualtCtor()
{
cout << "MyObjNoDefualtCtor::~MyObjNoDefualtCtor - address is" << this << endl;
}
// just to be sure - explicitly disable the defualt ctor
MyObjNoDefualtCtor() = delete;
int m_a;
};
int main(int argc, char** argv)
{
// create a vector and reserve 10 int's for it
// NOTE: no insertion (of any type) has been made into the vector.
vector<int> vec1;
vec1.reserve(10);
// try to access the first element - due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
size_t index = 0;
cout << "vec1[" << index << "]:" << vec1[index] << endl;
// now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single
// element to the vector, I would excpet here an excpetion to be thrown.
index = 9;
cout << "vec1[" << index << "]:" << vec1[index] << endl;
// same thing goes for user defined type (MyObjNoDefualtCtor) as well
vector<MyObjNoDefualtCtor> vec2;
vec2.reserve(10);
// try to access the first element - due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
index = 0;
cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;
// now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
index = 9;
cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;
return 0;
}
Notes:
The sample code is compiled with -std=c++11 option.
Compiler version is g++ 5.4 (on my Ubuntu 16.04 machine).
Thanks,
Guy.
A vectors operator[] function may or may not do bounds-checking. The implementations that do have bounds-checking, typically only does it for debug-builds. GCC and its standard library doesn't.
The at function on the other hand, does have mandatory bounds-checking and will be guaranteed to throw an out_of_range exception.
What happens here is simply that you go out of bounds and have undefined behavior.
Is at() that perform the range check, not (necessarily) operator[].
Your code have udefinded behaviour.
If you want to be sure to get an exception, use
vec1.at(index)
instead of
vec1[index]
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
Today I try something like this in VS2012 and Max OS 10.7
vector<int> vec;
vector<int> vec2;
for(int i = 0;i < 100 ;i++){
vec.push_back(i);
}
cout << "size: " << vec.size() << endl;
cout << "capacity: " << vec.capacity() << endl;
cout << vec[127] << endl;
//vec2.reserve(10);
fill_n(vec.begin(),128,-1);
cout << vec[127] << endl;
return 0;
as we know the size of vector is the real number of elements in the container, the code above can cause runtime error in VS2012, but it works fine on Max OS, and I try it in Ideone.com and also run successfully, I am not sure if something wrong with the definition of size and capacity, why I can access element out of size?
PS: the capacity at this situation on my computer is 141 on VS2012 and 128 on Mac OS and Ideone.com
std::vector operator [] won't throw any out of range error. It's a undefined behaviour to access element greater than the vector size using [] operator.
Use std::vector::at instead, which throws std::out_of_range
Bump into this problem, I try to elaborate the answer from #P0W.
#1 Access element(s) of the 2d vector
If someone wants to access the elements of the 2d vector,
one should do the following and aware of the API 2dvector.at(row#).at(col#)
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector <vector<int> > vi;
vi.push_back( vector <int>() ); // add empty 1d vector
vi.at(0).push_back( 1 ); // push 1st element
cout << vi.at(0).at(0) << endl; // access element of 2d vector and prints 1
vi.at(0).at(0) = 2; // change number
cout << vi.at(0).at(0) << endl; // access element of 2d vector and prints 2
}
#2 std::out_of_range
if you have difficulty finding the example of std::out_of_range, here is one
example code
// out_of_range example
#include <iostream> // std::cerr
#include <stdexcept> // std::out_of_range
#include <vector> // std::vector
int main (void) {
std::vector<int> myvector(10);
try {
myvector.at(20)=100; // vector::at throws an out-of-range
}
catch (const std::out_of_range& oor) {
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
return 0;
}
output
Out of Range error: vector::_M_range_check
i'm trying to store some elements that is going to change every time, but i don't know which
way is better and why. I'm thinking about two ways, 1) declaring array of int and loop or
use vector's.
Which way is better and why?
Does declaring array of int have any future memore problems as leak?
the code down below show the two ways i'm talking about:
1)
#include <iostream>
#include <vector>
int main()
{
int x[5];
x[0] = 10;
x[1] = 20;
x[2] = 30;
x[3] = 40;
x[4] = 50;
for(unsigned int i = 0;i<=sizeof(x[5]); i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
2)
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(10);
x.push_back(20);
x.push_back(30);
x.push_back(40);
x.push_back(50);
for(unsigned int i = 0;i<=x.size()-1; i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
If this is all you have to do, and your array will always have a size that is known at compile time, then you do not need std::vector.
On the other hand, in C++11 you could use std::array instead of a plain C array (std::array is a zero-overhead, safer and more functional wrapper over a C array):
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> x = { 10, 20, 30, 40, 50 };
for (unsigned int i = 0; i < x.size(); i++)
// ^^^^^^^^
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
}
Here is a live example. Notice, that std::array offers a size() member function which you may want to use instead of the sizeof operator.
Moreover, since std::array is a standard sequence container, you could iterate through its element this way:
std::size_t i = 0;
for (auto e : x)
{
std:: cout << "x[" << i++ << "] = "<< e << std::endl;
}
Here is a live example.
If the size is known at compile time, use std::array. If not, use std::vector. In either case, use iterators to look at the elements:
typedef std::array<int> my_container_type;
typedef my_container::iterator iterator;
my_container_type my_container = { whatever };
for (iterator it = my_container.begin(); it != my_container.end(); ++it)
std::cout << "x[" << (it - my_container.begin()) << "] = " << *it << '\n';
By using iterators you greatly reduce the risk of accidentally using a loop limit like sizeof(x[5]), which is nonsense.
Neither is "better". They both address entirely different use cases.
If you know the array size at compile time and are 100% sure it will never change, sure, use a plain old array. It has less overhead, and the compiler can even aid you with static analysis by spotting any attempts to read outside the boundaries.
On the other hand, if you are unsure of the array's side (i.e. you will be reading input from a file or the user), then use the std::vector. It can grow to any size to meet your needs.