views:

101

answers:

4
int arr[ 5 ] = { 0 };

int i = 8; // out of bounds

arr[ i ] = 8;

I know that I can just check i like this if( i < 0 || i > 5 ) ....

I also know about SEH in Visual Studio, but it looks like not working solution.

__try { /* code */ } 

__except(GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED)

This is not working. As I see SEH working in situations like divide to 0, access protected pages ... How can I protect my program from crashes?

+1  A: 

Use proper containers like std::vector and catch the exceptions?

fabrizioM
I knwo about containers and using it where possible, but what to do when I need arrays ?
Davit Siradeghyan
+4  A: 

There is no guarantee that SEH will catch this - it depends on your hardware detecting the access , which does not happen for all invalid array accesses. If you want to be sure of catching it, use the standard C++ std::vector container instead of an array, and access it via its at() member function, rather than the [] operator - this will raise a standard C++ exception if the access is invalid.

anon
Hi Neil Butterworth. I knwo about containers and using it where possible, but what to do when I need arrays ?
Davit Siradeghyan
@David As I said in my other comment, you very probably don't need to use arrays - I almost never use them in my own code. But if you do feel you need them, there is no guaranteed way of checking for access violations.
anon
Can Valgrind detect out of bounds access?
FredOverflow
@Fred Vagrind doesn't run on Windows.
anon
+2  A: 

You cannot protect yourself from this. If you want, you have to use another language that checks for you. C and C++ demand that you check yourself that you write safe code.

An alternative may be to wrap the array into a struct...

template<typename E, std::size_t s>
struct array {
  E &operator[](std::ptrdiff_t i) {
    assert(i < s && "out of range!");
    return d[i]; 
  }
  E const &operator[](std::ptrdiff_t i) const {
    assert(i < s && "out of range!");
    return d[i]; 
  }

  typedef E underlying_array[s];
  underlying_array &raw() { return d; }
  underlying_array const &raw() const { return d; }

  E d[s];
};


array<int, 5> arr = { 0 };
arr[8] = 8; /* assert will ring */
foo(arr.raw()); /* pass as an int[5] */

That class is provided by boost and C++0x too (however, without a raw function), but error checking is not required for them.

Johannes Schaub - litb
A: 

You have a couple of options:

  • don't use raw arrays (use std::vector or boost::array instead)
  • don't use C++

the only other option is to write code that does not contain any out-of-bounds errors

There is absolutely no way to reliably detect out-of-bounds errors on raw arrays in C++.

You could just catch the access violation that sometimes occurs, but that won't give you a correct program. You'll still go out of bounds in many other cases, overwriting previously allocated memory and corrupting other parts of your program.

jalf