最近,一个C++开发人员问他们为什么要得到这个代码的诊断信息:
[code lang=“cpp”]void示例(char const*const src,char*const dest){标准::复制(src,src+42,dest);}
如果在调试模式下编译此文件,将收到如下消息:
xutility(2350,1): warning C4996: 'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' _DEPRECATE_UNCHECKED(copy, _Dest); ^ xutility(2350): note: see declaration of 'std::copy::_Unchecked_iterators::_Deprecate' _DEPRECATE_UNCHECKED(copy, _Dest); . est.cpp(4): note: see reference to function template instantiation '_OutIt std::copy<const char,char*>(_InIt,_InIt,_OutIt)> ' being compiled with [ _OutIt=char *, _InIt=const char * ] std::copy(src, src + 42, dest);
这是由STL的迭代器调试支持引起的。如果启用调试(使用 /MTd
或 /MDd
),您要求STL为您检查结果范围的大小,如果您只给我们一个普通指针,就没有办法 std::copy
告诉你射程的终点在哪里。
您可以通过多种方式告诉STL范围的结束位置:
-
如果可能,可以传递std::copy普通数组。如果从数组开始,我们将看到数组的范围,并进行适当的边界检查。[code lang=“cpp”]//copy现在可以判断dest是1234个元素无效示例(char const*const src){char dest[1234];标准::复制(src,src+42,dest);}
-
几个标准库算法在C++ 14中接收到“双范围”版本。如果使用双范围版本,第二个范围已经提供必要的边界检查:[code lang=“cpp”]布尔示例(char const*const left,const sizeu t leftSize,char const*const right,const sizeu t rightSize){//触发器警告返回相等(left,left+leftSize,right);//好的返回equal(left,left+leftSize,right,right+rightSize);}
- 可以使用标准容器(如字符串或向量)返回目标。如果_ITERATOR_DEBUG_LEVEL不为零,则迭代器有足够的信息来知道它的结束位置,并提供适当的边界检查。
- 你可以用
stdext::make_checked_array_iterator
创建一个知道目标大小的迭代器。 - 您可以决定接受此区域中代码中可被利用的bug的风险,并定义
_SCL_SECURE_NO_WARNINGS
在项目中,或在包含任何STL头之前。有了这个设置,STL将在它能检查的地方进行边界检查,但是当它不能这样做时不会警告您。
你有什么问题要我们写出来吗?关于这个帖子或内容的其他反馈(如在特定场景中的C++教程)?请留下评论或电子邮件(ebattali@microsoft.com). 谢谢!