Google Test和std :: vector范围异常

时间:2013-01-11 15:50:21

标签: c++ exception vector googletest

我使用googletest测试我的C ++代码。如果由于使用错误的索引访问vector::_M_range_check而引发std::vector异常,则googletest会报告:

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

太好了,现在我也想知道哪个矢量,哪个指数和哪个范围。如何轻松获取此信息,将测试代码保留在googletest单元测试用例中?

(我几乎从Java开始很长一段时间IndexOutOfBoundsException ......)

3 个答案:

答案 0 :(得分:8)

如果您使用此命令行选项运行,那么您的异常将一直冒出:

--gtest_catch_exceptions=0

在调试器内执行此操作将为您提供异常的堆栈跟踪。

答案 1 :(得分:7)

此处不涉及Google Test。您的C ++标准库实现引发了异常,并且由C ++标准库实现来决定如何使其例外变得冗长。

由于您收到异常,我认为您使用的是std::vector::at而不是std::vector::operator[]。您可以采取几种方法来获取更多信息。

首先,您可以通过调用at替换对operator[]的调用(个人而言,我发现at的异常投掷范围检查非常有用,并且它确实有性能开销)并使用C ++标准库实现的迭代器调试。例如,使用g ++,如果我使用operator[]并使用-D_GLIBCXX_DEBUG进行编译以启用operator[]的范围检查,则会出现类似于以下内容的错误:

/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.

其次,您可以通过调用at或类似内容来取代对test_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);
}

答案 2 :(得分:0)

vector::at(size_type n)被记录为在无效out_of_range(23.2.3p17)上投掷nout_of_range不包含有关容器或索引的信息,因此如果您需要该信息,则必须包装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));
    }
  }
};

请注意,at不是虚拟的,因此您必须通过包装的at进行调用以获取嵌套异常。