C ++: блок Catch не перехватывается? - PullRequest
0 голосов
/ 23 октября 2011

У меня есть определенный класс Exception, который я хочу выбросить из метода класса и отловить его вызывающий код в функции main ().

Однако, когда я запускаю его, я получаю следующую ошибку: Unhandled exception at 0x775915ee in OpenHashTable.exe: 0xC0000005: Access violation. как будто это не обрабатывается. Я не понимаю, почему это происходит. Вот соответствующий код:

main() {
    ......
        case 'i':   
        {
                cout << "Enter the positive integer you wish to insert: ";
                    //Input Validation.  
                if (!(cin >> number))
                {
                    cout << "Please enter a valid positive integer...\n\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n'); //Taken from /2097890/horoshii-tsikl-proverki-vvoda-s-ispolzovaniem-cin-c
                    break;
                }
                try
                {
                    hashTable.add(abs(number)); //Add positive only integer
                }
                catch (FullTableException& fte)
                {
                    cout << "HashTable is full!" << endl;
                    break;
                }
                catch (DuplicateElementException& dee) //NOT BEING CAUGHT?
                {
                    cout << "HashTable already contains that element." << endl;     
                    break;
                }
                cout << abs(number) << " added!\n\n";
                break;
        }
     .......
}

Вот исключение, которое выдается в методе HashTable :: add ()

    //Adds an element into the appropriate index
bool OpenHashTable::add(int toAdd) throw(FullTableException, DuplicateElementException)
{
  int index = hash(toAdd);

  //Check for duplicate
  if (search(toAdd))
      throw DuplicateElementException();  //NOT ACTUALLY THROWING??

  if (arr[index] != 0) //If element is occupied   //GET AN ACCESS VIOLATION HERE
  {
      int j = 0;

      //Linear Probing...
      for ( unsigned int i = index + 1; j < 100; i = ((i+1) % 100) )
      {
          if (arr[i] != 0 && arr[i] != -1) //If element is occupied
          {
              j++;          //Keep count of how many tries, for full array
              continue;
          }
          else
          {
              arr[i] = toAdd;   //Add to array
              size++;           //Increment size
              break;
          }

      }
      if (j == 100) //We've checked all possible elements
          throw FullTableException();   //No spaces
  }
  else
  {
      arr[index] = toAdd;   //Add to array straight away
      size++;               //Increment size
  }
  return true;  //Successfully added

}

РЕДАКТИРОВАТЬ: метод поиска ():

    bool OpenHashTable::search(int toSearch)
{
    int index = hash(toSearch);

if (arr[index] == toSearch)
    return true;    //Found at index
else
{
    int j = 0;
        //Linear search for value
    for ( unsigned int i = index + 1; j < 100; i = ((i+1) % 100) )
    {
        if (arr[i] == toSearch)
            return true;    //found
        else if (arr[i] == 0)
            return false;   //Not in HashTable
        else 
            continue;   //Probe next element
    }
    if (j == 100)
        return false;   //Not in HashTable
}
return true;
}

РЕДАКТИРОВАТЬ: _ try ... _except () Стек вызовов:

    ntdll.dll!775915ee()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
ntdll.dll!775915ee()    
ntdll.dll!7761852f()    
ntdll.dll!776372ec()    
ntdll.dll!7760063e()    
ntdll.dll!775fabf9()    
ntdll.dll!77580143()    
KernelBase.dll!75c5b9bc()   
KernelBase.dll!75c5b9bc()   
KernelBase.dll!75c5b9bc()   
msvcr100d.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo)  Line 157   C++
OpenHashTable.exe!OpenHashTable::add(int toAdd)  Line 100   //THIS IS "throw DuplicateElementException()"

OpenHashTable.exe!main()  Line 267    //THIS IS "hashTable.add(abs(number));"

РЕДАКТИРОВАТЬ: DuplicateElementException:

//Just an empty class
class DuplicateElementException : public exception
{
private:
public:
    DuplicateElementException();   //Constructor
    ~DuplicateElementException();   //Destructor
};
//empty constructor and destructor definitions...

Любая помощь очень ценится.

Спасибо

Calum

Ответы [ 4 ]

5 голосов
/ 23 октября 2011

Исключением является исключение SEH "Нарушение прав доступа", которое означает, что вы читаете или пишете с неверного адреса.Это, вероятно, ошибка в search или hash.и ваша программа не доходит до строки, где вы бросаете DuplicateElementException.

Кроме того, спецификация исключений (бросок после прототипа функции) устарела, поэтому не используйте их.

4 голосов
/ 23 октября 2011

Возникающее исключение Access access является исключением SEH и не будет перехвачено блоком C ++ catch. Скорее всего, вы пишете за пределами какого-либо массива, который вызывает исключение.

Чтобы устранить проблему, окружите все, что находится внутри кода main, в блоке __try и поместите точки останова в сопровождающий блок __except. Подробную информацию о том, как это сделать, можно найти в документах MSDN . Вы можете использовать код там почти дословно. Запустите вашу программу в режиме отладки, и при достижении точки останова осмотрите стек вызовов, чтобы выяснить, на какую строку выдается исключение SEH.

Кроме того, если у вас нет веских причин использовать массив C, вы должны использовать std::array (если размер массива фиксирован) или std::vector для хеш-таблицы. В Visual Studio operator[] для обоих из них будут выполняться проверки диапазона в режиме отладки и выдается исключение std::out_of_range, если ваш индекс выходит за пределы. Вы также можете использовать функцию-член at() с обоими, чтобы они также выполняли проверку границ в режиме Release. В любом случае отладку намного проще, чем возиться с SEH.

EDIT:
Немного рефакторинга кода потребуется для отладки проблемы с использованием __try - __except, потому что вы не можете окружить код, содержащий уничтожение объектов C ++, __try.

Чтобы обойти это, создайте функцию с именем int mainHelper() и переместите весь код из main в эту функцию. Теперь ваш код должен выглядеть так:

int mainHelper()
{
  /* All your code from main goes here */
}

int main()
{
  __try {
    return mainHelper();

  } __except( filter(GetExceptionCode(), GetExceptionInformation()) ) {
    puts("in except");

  }
}
0 голосов
/ 23 ноября 2011

Существует очень простой способ отловить любое исключение (деление на ноль, нарушение доступа и т. Д.) В Visual Studio с помощью блока try -> catch (...). Незначительная настройка проекта достаточно. Просто включите опцию / EHa в настройках проекта. См. Свойства проекта -> C / C ++ -> Генерация кода -> Установите для параметра Разрешить исключения C ++ значение «Да с исключениями SEH» . Вот и все!

Подробности здесь: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

0 голосов
/ 23 октября 2011

Кажется, что индекс выходит за пределы массива обр. Это делает ваш процесс читаемым из памяти, которая ему не выделена, и вылетает. Это не исключение C ++, а то, что операционная система сообщает вашей программе.

...