将指针包装到迭代器中以便复制到STL容器中

时间:2015-10-22 13:09:07

标签: c++ stl iterator

我有一个指向某些数据的指针,我想把它放入一个字符串中。我认为使用std::copy应该是最安全的方法。

但是,在Visual Studio 2010中,我收到警告

  

警告C4996:'std :: _ Copy_impl':带有可能不安全的参数的函数调用 - 此调用依赖于调用者来检查传递的值是否正确。要禁用此警告,请使用-D_SCL_SECURE_NO_WARNINGS。

当然警告是正确的。 MSDN checked_array_iterator上描述了一些checked_array_iterator个对象,可用于包装这样的指针并使其与STL迭代器兼容。

问题是,这个checked_array_iterator只能用作目标,而不能用作来源。

因此,当我尝试使用它时,应用程序崩溃或无法编译:

char buffer[10] = "Test";
std::string s;

// These are parameters from an external call and only shown here to illustrate the usage.
char *pTargetAdress = &s;
const char *oBegin = buffer;
const char *oEnd = oBegin+sizeof(buffer);

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
std::copy(oBegin, oEnd, p->begin());   // crash

stdext::checked_array_iterator<const char *>beg(oBegin, oEnd-oBegin);
stdext::checked_array_iterator<const char *>end(oEnd, 0);
std::copy(beg, end, p->begin());   // crash

stdext::checked_array_iterator<const char *>v(oBegin, oEnd-oBegin);
std::copy(v.begin(), v.end(), p->begin());   // doesn't compile

如果有便携式标准方式,我宁愿使用它而不是在MS扩展上进行重新打印。

2 个答案:

答案 0 :(得分:1)

在特定情况下,您可以使用std::string构造函数或assign()方法,请参阅cppreference

const char* pointer = ...;
std::size_t size = ...;

std::string string(pointer, size);
std::string string(pointer); // if null-terminated

顺便说一下,从static_cast转换为reinterpret_cast时,您应该使用void*代替T*

一般而言:

  

如果有便携式标准方式,我宁愿使用它而不是在MS扩展上进行重新打印。

这是Visual Studio 2015中最令人厌恶的警告之一。虽然它的消息 是真的,但对于在原始指针上使用std::copy()的每个人来说都应该是显而易见的。建议的checked_array_iterator解决方法不仅完全覆盖了一个简单的问题,而且还引入了非标准类,从而使您的代码不可移植。

如果我是你,我会定义_SCL_SECURE_NO_WARNINGS并在没有警告的情况下再次编译完全有效的C ++代码。

答案 1 :(得分:1)

指针非常好(随机访问) - 指针。问题在于您将数据复制到坏内存中。 p->begin()等于s.begin(),等于s.end()指向无效内存。要解决此问题,您可以使用例如

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
p->resize(oEnd - oBegin); //resize to make room for the data
std::copy(oBegin, oEnd, p->begin());   // no more crash

或者

#include <iterator>

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
std::copy(oBegin, oEnd, std::back_inserter(*p));   // copy by appending to the end

或者可能只是

std::string *p = reinterpret_cast<std::string *>(pTargetAdress);
*p = std::string(oBegin, oEnd);   // copy by temporary
相关问题