1

I am trying to get my program to throw a std::range_error if the array index my function is accessing is out of bounds. The type passed in is size_t, because the memory location in the stack may be signed or unsigned.

Here is what I have tried:

MyClass::MyClass(){ // Default constructor
    size = 10;
    ptr = new int[size];
}

int MyClass::at(size_t position) const
{
    try
    {
        return ptr[pos];
    }
    catch (const std::range_error&)
    {
        cout << "Range Error" << endl;
    }
}

int main() {
    // Test exceptions
    MyClass a;
    throw_(a.at(0), range_error);
}

How can my function be corrected so it throws a range_error when the index is out of bounds?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • You're catching an exception where you should be checking validity and throwing instead. – interjay Mar 30 '21 at 21:35
  • 1
    The java stack-overflow group is over that way ---> – Mike Vine Mar 30 '21 at 21:36
  • 3
    This was asked earlier today. Does this answer your question? https://stackoverflow.com/questions/66875237/does-try-catch-catches-run-time-error-especially-out-of-range-error/66875429#66875429 – François Andrieux Mar 30 '21 at 21:36
  • 3
    invoking undefined behavior is not the way to trigger an out-of-range exception. Apart from the fact that `std::range_error` isn't intended for this purpose (it's intended for *value* error that would breach some domain-limited restrictions, such as the only two places in the standard library that can actually throw this: string conversions), your code should verify `position` is within the `[0...size)` and if detected not in range, throw a `std::out_of_range` exception (which is intended precisely for such conditions). – WhozCraig Mar 30 '21 at 21:42
  • 1
    Can you change your class to use `std::vector` instead? If so, then you can simply use `vector::at()`, eg: `MyClass::MyClass() : vec(10) {} int MyClass::at(size_t position) const { return vec.at(pos); }` – Remy Lebeau Mar 30 '21 at 22:02
  • C++ is very unforgiving when it comes to guesswork. A lot of the time the compiler slaps down the code over bad syntax, but it's still really easy to write code that compiles and doesn't even come close to working as intended. It is also really easy to work around a compiler error and wind up having to deal with the runtime error the compiler error was trying to prevent. – user4581301 Mar 30 '21 at 22:02

1 Answers1

8

Your class should know the size of the array at all times. You can know immediately if the value passed is out of range and just throw.

Your try can't work. operator[]() doesn't throw. It functions as a simple memory offset.

Your function should look more like this:

int MyClass::at(size_t position) const
{
  if (position >= this->m_size) throw std::out_of_range("Bad idx passed to at()");

  return ptr[position];
}
sweenish
  • 4,793
  • 3
  • 12
  • 23