2011-10-23 77 views
0

我有一个特定的Exception类,我想从类方法抛出并捕获它在main()函数中的调用代码。C++:catch块不捕获?

但是,当我运行它,我得到以下错误: 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 http://stackoverflow.com/questions/2075898/good-input-validation-loop-using-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; 
     } 
    ....... 
} 

下面是哈希表抛出的异常: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 

} 

编辑:search()方法:

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; 
} 

编辑:_ 尝试... _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

+1

什么是你的搜索方法是什么?另外,你不应该通过表大小来修改哈希值吗? –

+0

已添加。不明白你的意思。散列函数简单地为'value%100'(100是表的大小) –

+0

请发布'DuplicateElementException'的内容 – Praetorian

回答

5

引发的异常是一个SEH异常“访问冲突”,这意味着你阅读或无效地址写。这可能是searchhash中的一个错误。并且你的程序没有到达你投掷的地方DuplicateElementException

此外,异常规范(函数原型之后的抛出)已被弃用,所以请勿使用它们。

+0

大多数编译器不以标准符合方式实现异常规范,但它们是否被正式弃用? –

+1

@Als:按照C++ 11,是的。 – ybungalobill

+0

感谢您的更新。它是关于时间他们摆脱那些:) –

0

看来索引超出了数组arr的范围。它使您的进程从内存中读取,但未分配给它并崩溃。这不是C++异常,而是操作系统告诉程序的东西。

+0

我不明白我可以如何访问越界。我使用索引3测试它,数组大小为100. –

+0

@CalumMurray您有两行代码: int index = hash(toSearch); if(arr [index] == toSearch) 在访问arr [index]之前,您应该检查hash(toSearch)返回的内容。 – selalerer

+0

你如何声明大小为100的arr? (我在你粘贴的代码中看不到它) – doctorlove

4

访问冲突抛出的异常是SEH异常,并且不会被C++ catch块捕获。你很有可能写一些数组的边界,这会导致异常被抛出。

要调试此问题,请将main中的代码内的所有内容都包含在__try块中,并将断点放在随附的__except块中。有关如何操作的详细信息,请参阅MSDN docs。你可以几乎逐字地使用那里的代码。在调试模式下运行程序,并在命中断点时检查调用堆栈以确定SEH异常正在抛出的行。另外,除非有令人信服的理由使用C数组,否则应该使用std::array(如果数组大小是固定的)或std::vector作为哈希表。在Visual Studio operator[]上,这两者都将在调试模式下执行范围检查,并在索引超出范围时抛出std::out_of_range异常。您也可以使用at()成员函数来让它们在发布模式下执行边界检查。在任何一种情况下,调试都比调试SEH更容易。

编辑:
代码重构一点点将需要调试使用__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"); 

    } 
} 
+1

顺便说一句,当用/ EHa编译时,SEH可以用catch(...)来捕获。 – ybungalobill

+1

@ybungalobill它可以,但我记得在某个地方看到那个选项并不是非常适合设置。不幸的是,我不记得所述的原因。 – Praetorian

+0

谢谢。我不确定在'__except(expression)'语句中作为表达式放置什么。我只使用大小为100的数组中的索引3,所以我看不到我会在哪里生成数组越界的错误。 –

-2

还有就是要捕捉任何类型的异常使用Visual Studio中尝试一个非常简单的方法(除零,访问冲突等) - >捕获(.. )块。一个小的项目调整就足够了。只需在项目设置中启用/ EHa选项。请参阅项目属性 - > C/C++ - >代码生成 - >将启用C++异常修改为“是有SEH异常”。而已!

查看详情这里: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

+0

您正在提供一个可能危险的解决方案,而无需说出其缺点。 – Steed

+0

我不是一个缺点。如果你知道的话,为什么你不告诉?对我来说,这个解决方案是完美的,比在这里投票的更好。 –

+0

在出界存储器访问,除零或其他异步(SEH)异常之后,'/ EHa'会导致您的程序混乱地跟随着损坏的状态。 – LThode