2013-01-11 40 views
6

googletestでC++コードをテストします。 std::vectorが間違ったインデックス、googletestレポートにアクセスされるためvector::_M_range_check例外がスローされた場合:Google Testとstd :: vectorの範囲例外

C++ exception with description "vector::_M_range_check" thrown in the test body. 

グレート、今私はまた、ベクター、インデックスと範囲を知りたいのです。この情報を簡単に取得して、グーグレテストユニットテストケースにテストコードを保存するにはどうすればよいですか?

+0

@gtest_catch_exceptions = 0 – JaredC

+0

@JaredCこのフラグは、例外がスローされた後にテストを終了しますが、出力は例外(ベクトル、インデックス、範囲)の起点に関する情報をもう与えません。 – clstaudt

+2

@cls:デバッガでテストしたり、終了後にコアダンプを調べたりすると、未処理の例外がスローされた場所がわかります。代わりに、 'std :: __ throw_out_of_range'にブレークポイントを置くこともできます。これはGNUライブラリが例外をスローするために呼び出す関数です。 –

答えて

8

あなたは、このコマンドラインオプションあなたの例外だろうバブルのすべての方法アウトで実行する場合:

--gtest_catch_exceptions=0 

これをデバッガの内部で実行すると、例外のスタックトレースが正確に得られます。

+0

エラーの原因としてインデックスと境界は正しくありません。 – clstaudt

+3

@clsこの情報は、デバッガが停止するとすぐに利用できます。 – JaredC

6

は、Googleのテストはここに関与していない(私はほとんど...その古き良きIndexOutOfBoundsExceptionとJava用の長い開始します)。あなたのC++標準ライブラリ実装は例外をスローしています。例外をどのようにして冗長にするかは、C++標準ライブラリの実装によって決まります。

例外が発生しているので、std::vector::operator[]の代わりにstd::vector::atを使用していることを前提としています。より多くの情報を得るために取ることができるアプローチには、いくつか考えられます。

まず、あなたは(個人的に、私は非常に有用であることを確認しatの例外が発生範囲を見つけることができませんし、それがパフォーマンスのオーバーヘッドを持っている)とあなたのC++標準を使用operator[]への呼び出しでatへの呼び出しを置き換えることができますライブラリ実装のイテレータデバッグ私はoperator[]を使用している場合たとえば、グラム++で、operator[]をチェックする範囲をオンにする-D_GLIBCXX_DEBUGでコンパイルし、私は次のようなエラーが出る:

/usr/include/c++/4.3/debug/vector:237:error: attempt to subscript container 
    with out-of-bounds index 0, but container only holds 0 elements. 

第二に、あなたはtest_atへの呼び出しでatへの呼び出しを置き換えることができますまたは類似:(未テスト)

template <typename T> 
T& test_at(std::vector<T>& v, size_t n) { 
    // Use Google Test to display details on out of bounds. 
    // We can stream additional information here if we like. 
    EXPECT_LT(n, v.size()) << "for vector at address " << &v; 

    // Fall back to at, and let it throw its exception, so that our 
    // test will terminate as expected. 
    return v.at(n); 
} 
0

vector::at(size_type n)は、無効(23.2.3p17)に投げてout_of_rangeと記載されています。 out_of_rangeは、コンテナまたはインデックスに関する情報を運ばないので、あなたは、あなたがその情報たい場合atをラップする必要があります:あなたが得るためにラップatを通じて呼び出す必要がありますのでatは、仮想ではない

template<typename T> struct my_vector: public std::vector<T> { 
    using std::vector<T>; 
    struct at_out_of_range: public std::out_of_range { 
    my_vector *vector; 
    size_type size; 
    size_type n; 
    at_out_of_range(my_vector *vector, size_type size, size_type n): 
     std::out_of_range("at_out_of_range"), vector(vector), size(size), n(n) {} 
    }; 
    reference at(size_type n) { 
    try { 
     return std::vector<T>::at(n); 
    } catch(std::out_of_range &ex) { 
     std::throw_with_nested(at_out_of_range(this, size(), n)); 
    } 
    } 
}; 

注ことをネストされた例外。