2011-10-23 16 views
0

は、私はクラスメソッドから投げると、それはmain()関数内のコードを呼び出しているからキャッチしたいんだ、特定の例外クラスを持っています。C++:キャッチブロックがキャッチしませんか?

私はそれを実行するとき、私は次のエラーを受け取ります: 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; 
     } 
    ....... 
} 

はここで例外が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 

} 

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

はEDIT:_ 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));" 

EDIT:DuplicateElementException:

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

すべてのヘルプははるかに高く評価されます。

おかげ

カルム

+1

検索方法では?また、テーブルサイズでハッシュ値を変更するべきではありませんか? –

+0

追加されました。よく分からない。ハッシュ関数は単純に 'value%100'(100はテーブルサイズ) –

+0

DuplicateElementExceptionの内容を投稿してください – Praetorian

答えて

5

スローされた例外を使用すると、読み取りまたは無効なアドレスから書き込みをすることを意味SEH例外「アクセス違反」、です。それはおそらくsearchまたはhashのバグです。そして、あなたのプログラムは、あなたがDuplicateElementExceptionをスローラインに取得していません。

また、例外指定(関数プロトタイプ後のスロー)が廃止され、ので、それらを使用しないでください。

+0

ほとんどのコンパイラは例外仕様を標準に準拠した方法で実装していませんが、正式に廃止されていますか? –

+1

@Als:C++ 11のとおり、はい。 – ybungalobill

+0

そのアップデートをありがとうございました:彼らはそれらを取り除く時間についてでした:) –

0

インデックスが配列arrの境界の外にあるように思えます。それはあなたのプロセスを割り当てられていないメモリから読み込み、クラッシュさせます。これはC++の例外ではありませんが、OSがプログラムに通知するものです。

+0

範囲外にアクセスする方法がわかりません。私は3のインデックスで配列をテストしており、配列のサイズは100です。 –

+0

@CalumMurray 2行のコードがあります。 int index = hash(toSearch); if(arr [index] == toSearch) arr [index]にアクセスする前に、どのようなハッシュ(toSearch)が返されるかを確認する必要があります。 – selalerer

+0

どのようにarrをサイズ100で宣言していますか? (あなたがペーストしたコードでは見えません) – doctorlove

4

アクセス違反例外がスローされるのはSEH例外であり、C++ catchブロックによってキャッチされません。いくつかの配列の境界を越えて書き込みが行われる可能性が最も高いため、例外がスローされます。

伴う__exceptブロック内__tryブロックと場所のブレークポイントにmain内のコード内のすべてのものを囲んで、問題をデバッグします。これを行う方法の詳細はMSDN docsで見つけることができます。このコードは、ほぼそのまま使用することができます。プログラムをデバッグモードで実行し、ブレークポイントがヒットしたときにコールスタックを調べて、SEH例外がスローされている行を特定します。

また、C配列を使用する理由がない場合は、std::array(配列のサイズが固定されている場合)またはハッシュテーブルのstd::vectorを使用する必要があります。 Visual Studioの場合operator[]は両方ともデバッグモードで範囲チェックを行い、インデックスが範囲外の場合はstd::out_of_range例外をスローします。両方ともat()メンバ関数を使用して、リリースモードで境界チェックを実行することもできます。どちらの場合でも、SEHのものを混乱させるよりもデバッグするのがずっと簡単です。

EDIT:
リファクタリングの少し__try使用して問題をデバッグする必要があります - あなたは__tryとC++オブジェクトの破壊を含むコードを囲むことができないため__exceptを。

これを回避するには、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でコンパイルすると、Btw、SEHは 'catch(...) 'で捕まえることができます。 – ybungalobill

+1

@ybungalobillそれはできますが、私はどこかでそのオプションを設定することはあまり望ましくないことを覚えています。残念ながら、私は述べられた理由を覚えていません。 – Praetorian

+0

ありがとうございます。私は '__except(expression)'ステートメントの式として何を入れるべきか分かりません。私は100の配列の中で3のインデックスしか使用していないので、どこから範囲外の配列を生成するのかわかりません。 –

-2

試みを使用してVisual Studioでの例外のいずれかの種類(ゼロ除算、アクセス違反など)をキャッチする非常に簡単な方法があります - >キャッチ(.. 。)ブロック。マイナープロジェクトの調整があれば十分です。プロジェクト設定で/ EHaオプションを有効にするだけです。 プロジェクトのプロパティ - > C/C++ - >コード生成 - > C++例外を "Yes with SEH Exceptions"に変更してください。を参照してください。それでおしまい!

は、ここに詳細を参照してください: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

+0

あなたは、その欠点の言葉を言うことなく、おそらく危険な解決策を提供しています。 – Steed

+0

私は欠点の道具ではありません。あなたが何かを知っているならば、あなたは伝えませんか?私の場合、このソリューションは完璧なものであり、ここではより高い評価を受けています。 –

+0

'/ EHa'は、プログラムが境界外のメモリアクセス、ゼロ除算、または他の非同期(SEH)例外の後に混乱して混乱して混乱する可能性があります。 – LThode

関連する問題