发布模式下迭代器的边界检查(c++)

Posted

技术标签:

【中文标题】发布模式下迭代器的边界检查(c++)【英文标题】:bound check for iterator in Release mode (c++) 【发布时间】:2012-01-14 18:38:45 【问题描述】:

我故意让迭代器的大小超过std::vectorlike,

for (std::vector <Face>::iterator f = face.begin();
          f!=face.end()+5;
               ++f)

    // here I try to access (*f).P
    // note that I added 5 to the face.end()

在编译和运行时我都没有遇到任何错误。我怎样才能防止这种情况发生?

【问题讨论】:

不要那样做?至于检测,搜索checked iterators 调试版本通常会捕捉到这一点 我使用 Release 是因为需要运行时性能。 @Shibli:您需要使用 both 配置。一个叫做“Debug”,另一个叫做“Release”是有原因的。在准备好发布之前,您不想放弃额外的调试测试。 我以前没想过。它在调试中给出了运行时错误。谢谢。 【参考方案1】:

如果您想检查对vector 元素的访问,您可以使用at 函数,该函数在边界冲突的情况下抛出std::out_of_range 异常。示例:

for (std::vector<Face>::size_type i = 0;
          i != face.size()+5;
               ++i)

    face.at(i).f();

标准没有指定任何检查的迭代器。标准中的措辞是访问无效的迭代器会导致未定义的行为。但是许多实现提供了检查迭代器。如果可移植性不是问题,您可以使用其中一个检查过的迭代器。例如,在 MSVC 调试模式下,vector&lt;T&gt;::iterator 是一个检查迭代器。然而,在发布模式下,它只是 T* 的 typedef

【讨论】:

在调试模式下,它发现错误而不使用at。由于没看懂你的最后一句话,在release模式下我是不是应该用at检查一下? @Shibli:检查不是免费的。如果你想抛出异常,那么你应该使用 at。如果你知道你的所有边界都是正确的并且不希望有额外的检查开销,那么不要使用 at。【参考方案2】:

您使用的是什么 C++ 编译器? debug build 中的 VC10(即 VS2010 中的 C++ 编译器)正确识别问题:

// Compile with:
// cl /EHsc /W4 /nologo /D_DEBUG /MDd test.cpp


#include <iostream>
#include <string>
#include <vector>


class Face

public:
    std::string Name;

    explicit Face(const std::string & name)
      : Name(name)
    
;


int main()

    std::vector<Face> faces;
    faces.push_back( Face("Connie") );
    faces.push_back( Face("John") );

    for (
        std::vector <Face>::iterator f = faces.begin();
        f != faces.end() + 5;
        ++f)
    
        std::cout << f->Name << std::endl;
    

    return 0;

执行生成的 .exe 时,会显示一个错误对话框,其中包含以下错误消息:

表达式:向量迭代器 + 超出范围的偏移量

【讨论】:

@Shibli:不客气。 MS Visual C++ 附带的 STL 实现非常适合用于调试目的,其检查迭代器和调试迭代​​器支持。【参考方案3】:

对于标准 C++ 库的发布版本,您不会对迭代器(或其他可能未检查的操作)进行内置边界检查,因为它会比较慢。但是,这并不意味着您需要在调试模式下进行编译:据我所知,libstdc++ 调试模式可以在打开编译器优化的情况下进行编译。我怀疑其他检查的 STL 实现也是如此,因为检查的代码通常只是通过适当地设置一些宏来引导。为此,您需要找到适当的宏设置,并使用您用于构建代码的任何内容进行适当的设置。

【讨论】:

以上是关于发布模式下迭代器的边界检查(c++)的主要内容,如果未能解决你的问题,请参考以下文章

Python 3:检查迭代器的下一个值而不进行迭代

C++ 的STL中,迭代器那个指针为何++能指向下一个元素?

C++ 迭代器iterator的实现原理

C++ 标准库值操作迭代器的常见函数

c++ 迭代器库

为啥 c++ 顺序访问迭代器的函数签名不使用指针?