Pieter
Pieter

Reputation: 2711

C++ handling unanticipated errors

I need to learn C++ basics for a research project, and I'm experimenting with error/exception handling. I did use the throw command successfully to anticipate on events that might occur (like divide by zero), but I cannot figure out how to catch unanticipated exceptions. Take this example code:

#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;

void arrayOutOfBound()
{
    int a[3] = {1, 2, 3};

    try
    {
        cout << "This should not display: " << a[5] << endl;
    }
    catch(runtime_error &e)
    /* catch(exception &e)     // also does not work  */
    {
        cout << "Error: " << e.what() << endl;
    }
}

int main()
{
    arrayOutOfBound();
}

I guess I have to use throw statements somewhere, but suppose I really did not know that a[5] wouldn't work (or the user entered this index and I did not check for the array size), then how can I prevent the program from crashing? (as this happens in the Visual C++ Express 2010 debugger)

Note: if I would do try { int result = a[5]; } first, outside the block, and try to use cout << result at the end, the program does not compile. The compiler is trying to help me, but therefore I cannot try the exception handling.

Upvotes: 3

Views: 6352

Answers (5)

xxx374562
xxx374562

Reputation: 226

You could have caught the array bound error had you used std::array, instead of C style array, and the .at() member function

std::array <int, 5> stdArray = {1, 2, 3, 4, 5};

//array boundary check

 try  {
        cout << "trying to access out of bound element " << endl;
        cout << stdArray.at(5) << endl;
 } catch(std::exception &e) {
        cout << "Error: " << e.what() << endl;
  }

Now the program does not crash, instead, you see this output Error: array::at: __n (which is 5) >= _Nm (which is 5)

Upvotes: 1

mohaps
mohaps

Reputation: 1020

Sorry can't resist quoting an obvious meme "native arrays... that's not how you do it!" :D

the code you've written above uses a native array which is in essence a memory location. so by saying a[5] you're saying i want to use the 4 bytes at address (a + 4 * sizeof(int)) to be interpreted as an int. This won't throw an exception. it is undefined behavior and might return garbage. if you use -O2 or some such compiler flag, it MAY return 0 and btw, this is a grade A source of buffer overrun :D

Here's a template class that'll solve your problems:

#include <iostream>
#include <exception>
#include <stdexcept>
#include <vector>
using namespace std;

template<class T, size_t COUNT>
class CheckedArray
{
public:
    class OutOfBounds : public std::exception
    {
        public:
            virtual const char* what() const throw(){ return "Index is out of bounds"; }    
    };
    CheckedArray(){}
    virtual ~CheckedArray(){}
    const T& operator[] (size_t index) const
    {
        if(index >= COUNT){ throw OutOfBounds(); }
        return m_array[index];
    }
    T& operator[] (size_t index)    
    {
        if(index >= COUNT){ throw OutOfBounds(); }
        return m_array[index];
    }
private:
    T m_array[COUNT];
};
void arrayOutOfBound()
{
    //int a[3] = {1, 2, 3};

    CheckedArray<int,3> a;
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    try
    {
        cout << "This should not display: " << a[5] << endl;
    }
    catch(std::exception& e)     // this will kick in
    {
        cout << "Error: " << e.what() << endl;
    }
}


int main()
{
    arrayOutOfBound();
}

Upvotes: 2

John
John

Reputation: 540

If you simply want a handler for segmentation faults and such, you should check out signal.h

//John

Upvotes: 0

ndkrempel
ndkrempel

Reputation: 1936

If you want this behavior, recommend you write a class e.g. "CheckedArray" which wraps an array and performs bounds checking. If you do this in full generality, it will be a template class and you will need to know about overloading operator[] of course.

Alternatively, if you're happy with the overhead of a dynamically allocated array, use std::vector, in particular its at member function throws an exception on out-of-range index. As a side benefit, your array can now be (re)sized at run-time.

Even better, use std::array which also has the throwing at function (but is not resizable.)

Upvotes: 1

K-ballo
K-ballo

Reputation: 81389

suppose I really did not know that a[5] wouldn't work (or the user entered this index and I did not check for the array size), then how can I prevent the program from crashing?

You simply can't. An out of bounds access to an array causes undefined behavior in C++, it won't throw an exception. When you are lucky enough, you get a crash.

Upvotes: 3

Related Questions