2

How do I catch wrong array reference in C++? Why doesn't the following code work:

    #include <exception>

    int * problemNum = new int;
    int (* p [100])() = {problem1, problem2, problem3};

    ...

    try {
        cout << (*p[*problemNum-1])();
    }
    catch (exception){
        cout << "No such problem";
    }

My compiler says: Unhandled exception at 0xcccccccc in Euler.exe: 0xC0000005: Access violation. when I initiate bad reference by inputting 0 as *problemNum.

alamar
  • 18,729
  • 4
  • 64
  • 97
Alex
  • 43,191
  • 44
  • 96
  • 127

2 Answers2

4

alamar is right - C++ won't catch exceptions with this type of array.

Use an STL vector instead:

#include <exception>
#include <vector>

int * problemNum = new int;
std::vector<int(*)()> p;
p.push_back(problem1);
p.push_back(problem2);
p.push_back(problem3);

...

try {
    cout << p.at(*problemNum-1)();
}
catch (exception){
    cout << "No such problem";
}
Adam Pierce
  • 33,531
  • 22
  • 69
  • 89
  • 2
    That won't trigger an exception, either. If you need an exception when accessing an out-of-bounds element, use the "at" member function, not the bracket operator. – Rob Kennedy May 22 '09 at 22:30
  • Dang you're right Rob, I never knew that! I'll change the code example. – Adam Pierce May 22 '09 at 22:36
3

Becauce C++ can't handle such errors with its exception mechanism. See Defective C++ on that issue.

Use sigaction(2).

sigaction - examine and change a signal action

SYNOPSIS

   #include <signal.h>

   int sigaction(int signum, const struct sigaction *act,
                 struct sigaction *oldact);

DESCRIPTION The sigaction() system call is used to change the action taken by a process on receipt of a specific signal. signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP. If act is non-null, the new action for signal signum is installed from act. If oldact is non-null, the previous action is saved in oldact. The sigaction structure is defined as something like:

       struct sigaction {
           void     (*sa_handler)(int);
           void     (*sa_sigaction)(int, siginfo_t *, void *);
           sigset_t   sa_mask;
           int        sa_flags;
           void     (*sa_restorer)(void);
       };

You need to catch SIGSEGV, you can attach your own handler (function which gets called when illegal memory access is performed).

alamar
  • 18,729
  • 4
  • 64
  • 97
  • You really don't want to start catching SIGSEGV in this case. It's absolutely wrong to use segmentation faults as an array boundary check. Better just use std::vector. – sth May 22 '09 at 22:35