发布模式下迭代器的边界检查(c++)
Posted
技术标签:
【中文标题】发布模式下迭代器的边界检查(c++)【英文标题】:bound check for iterator in Release mode (c++) 【发布时间】:2012-01-14 18:38:45 【问题描述】:我故意让迭代器的大小超过std::vector
like,
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<T>::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++)的主要内容,如果未能解决你的问题,请参考以下文章