3

研究プロジェクトのために C++ の基礎を学ぶ必要があり、エラー/例外処理を試しています。発生する可能性のあるイベント (ゼロ除算など) を予測するためにコマンドを正常に使用しthrowましたが、予期しない例外をキャッチする方法がわかりません。このコード例を見てください:

#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;

void arrayOutOfBound()
{
    int a[3] = {1, 2, 3};

    try
    {
        cout << "This should not display: " << a[5] << endl;
    }
    catch(runtime_error &e)
    /* catch(exception &e)     // also does not work  */
    {
        cout << "Error: " << e.what() << endl;
    }
}

int main()
{
    arrayOutOfBound();
}

どこかでステートメントを使用する必要があると思いますが、それが機能throwしないことを本当に知らなかったとa[5]します (または、ユーザーがこのインデックスを入力し、配列のサイズを確認しませんでした)、どうすればプログラムがクラッシュするのを防ぐことができますか? (これは Visual C++ Express 2010 デバッガーで発生するため)

注:try { int result = a[5]; }ブロックの外側で最初に実行cout << resultし、最後に使用しようとすると、プログラムはコンパイルされません。コンパイラは私を助けようとしていますが、例外処理を試すことができません。

4

5 に答える 5

3

a [5]が機能しないことを本当に知らなかった場合(またはユーザーがこのインデックスを入力し、配列サイズを確認しなかった場合)、プログラムがクラッシュするのを防ぐにはどうすればよいですか?

あなたは単にできません。配列への範囲外のアクセスは、C ++で未定義の動作を引き起こし、例外をスローしません。運が良ければ、クラッシュします。

于 2012-05-22T23:54:22.810 に答える
2

申し訳ありませんが、明らかなミーム「ネイティブアレイ...それはあなたのやり方ではありません!」を引用することに抵抗することはできません。:D

上で書いたコードは、本質的にメモリ位置であるネイティブ配列を使用します。つまり、a [5]と言うと、アドレス(a + 4 * sizeof(int))の4バイトを使用してintとして解釈したいということです。これは例外をスローしません。これは未定義の動作であり、ガベージを返す可能性があります。-O2またはそのようなコンパイラフラグを使用する場合、0とbtwを返す可能性があります。これは、バッファオーバーランのグレードAのソースです:D

問題を解決するテンプレートクラスは次のとおりです。

#include <iostream>
#include <exception>
#include <stdexcept>
#include <vector>
using namespace std;

template<class T, size_t COUNT>
class CheckedArray
{
public:
    class OutOfBounds : public std::exception
    {
        public:
            virtual const char* what() const throw(){ return "Index is out of bounds"; }    
    };
    CheckedArray(){}
    virtual ~CheckedArray(){}
    const T& operator[] (size_t index) const
    {
        if(index >= COUNT){ throw OutOfBounds(); }
        return m_array[index];
    }
    T& operator[] (size_t index)    
    {
        if(index >= COUNT){ throw OutOfBounds(); }
        return m_array[index];
    }
private:
    T m_array[COUNT];
};
void arrayOutOfBound()
{
    //int a[3] = {1, 2, 3};

    CheckedArray<int,3> a;
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    try
    {
        cout << "This should not display: " << a[5] << endl;
    }
    catch(std::exception& e)     // this will kick in
    {
        cout << "Error: " << e.what() << endl;
    }
}


int main()
{
    arrayOutOfBound();
}
于 2012-05-22T23:58:38.970 に答える
1

この動作が必要な場合は、配列をラップして境界チェックを実行する「CheckedArray」などのクラスを作成することをお勧めします。これを完全に一般的に行う場合、それはテンプレートクラスになり、もちろん、演算子[]のオーバーロードについて知っておく必要があります。

または、動的に割り当てられた配列のオーバーヘッドに満足している場合は、を使用std::vectorします。特に、そのatメンバー関数は範囲外のインデックスで例外をスローします。副次的な利点として、実行時にアレイのサイズを(再)変更できるようになりました。

さらに良いことstd::arrayに、スローat機能も備えているものを使用してください(ただし、サイズ変更はできません)。

于 2012-05-22T23:57:56.967 に答える
0

セグメンテーション違反などのハンドラーが必要な場合は、signal.hを確認する必要があります。

//ジョン

于 2012-05-23T00:02:18.530 に答える