我有一个指向某些数据的指针,我想把它放入一个字符串中。我认为使用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扩展上进行重新打印。
答案 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