27

我正在使用 Visual Studio 2008。

我知道 std::vector 使用 at() 函数进行边界检查,并且如果您尝试使用运算符 [] 错误地访问某些内容(超出范围),则会出现未定义的行为。

我很好奇是否可以通过边界检查来编译我的程序。这样,operator[] 将使用 at() 函数并在任何超出范围时抛出 std::out_of_range 。

发布模式将在没有对 operator[] 的边界检查的情况下进行编译,因此性能不会降低。

我开始考虑这个问题是因为我正在将使用 Borland C++ 编写的应用程序迁移到 Visual Studio,并且在一小部分代码中我有这个(i=0,j=1):

v[i][j]; //v is a std::vector<std::vector<int> >

向量 'v' 的大小是 [0][1] (所以向量的元素 0 只有一个元素)。这是未定义的行为,我知道,但 Borland 在这里返回 0,VS 正在崩溃。我更喜欢崩溃而不是返回 0,所以如果我可以通过抛出 std::out_of_range 异常来获得更多的“崩溃”,迁移将更快地完成(因此它会暴露 Borland 隐藏的更多错误)。

4

5 回答 5

28

operator[]默认情况下,Visual Studio 2005 和 2008 已经在调试和发布版本中进行边界检查。

控制此行为的宏是_SECURE_SCL. 将其设置为 0 以禁用边界检查。

他们目前在 VS2010 中的计划是在发布版本中默认禁用边界检查,但在调试中保持启用。(宏也被重命名为_ITERATOR_DEBUG_LEVEL。我不知道是否有任何正式的文档可用,但这里这里已经提到过)

于 2009-08-17T21:33:45.887 回答
15

启用标志 _GLIBCXX_DEBUG 对 STL 容器进行边界检查,如下所述:http: //gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html

于 2010-04-17T03:20:23.987 回答
4

我过早地问了这个问题,但无论如何我都会发布答案,所以我正在分享一些知识。

在调试模式下编译时,在 Visual Studio 中实现的 stl 已经进行了边界检查。这可以在<vector>标题中看到:

reference operator[](size_type _Pos)
        {   // subscript mutable sequence

 #if _HAS_ITERATOR_DEBUGGING
        if (size() <= _Pos)
            {
            _DEBUG_ERROR("vector subscript out of range");
            _SCL_SECURE_OUT_OF_RANGE;
            }
 #endif /* _HAS_ITERATOR_DEBUGGING */
        _SCL_SECURE_VALIDATE_RANGE(_Pos < size());

        return (*(_Myfirst + _Pos));
        }

所以有对向量类的边界检查。我没有查看其他容器,但我相信它们具有相同的机制。

于 2009-08-17T21:13:41.293 回答
0

我现在无法访问任何 Windows 机器。但是,如果我在我的 mac os x 机器上查看 g++ 提供的 STL 实现,来自 /usr/include/c++/4.0.0/bits/stl_vector.h :

  // element access
  /**
   *  @brief  Subscript access to the data contained in the %vector.
   *  @param n The index of the element for which data should be
   *  accessed.
   *  @return  Read/write reference to data.
   *
   *  This operator allows for easy, array-style, data access.
   *  Note that data access with this operator is unchecked and
   *  out_of_range lookups are not defined. (For checked lookups
   *  see at().)
   */
  reference
  operator[](size_type __n)
  { return *(begin() + __n); }

未执行检查,尽管在 DEBUG 模式下发生事件。在此代码中未检出 _GLIBCXX_DEBUG 宏。

查看您自己的随 MSVC 交付的 STL 实现,看看做了什么。如果在任何情况下都没有进行检查......你别无选择,只能使用 at().. :-(

于 2009-08-17T21:14:52.633 回答
-4

为了速度,C++ 将向量运算符 [] 定义为不抛出异常。

我建议您在调试配置中测试应用程序一段时间,直到您确信主要的“隐藏”错误已经消失。

于 2009-08-17T21:10:02.847 回答