将此代码放入 MS Visual C++ 2010,编译(调试或发布),insert() 循环会崩溃,但 push_back 循环不会:
#include <vector>
#include <string>
using std::vector;
using std::string;
int main()
{
vector<string> vec1;
vec1.push_back("hello");
for (int i = 0; i != 10; ++i)
vec1.push_back( vec1[0] );
vector<string> vec2;
vec2.push_back("hello");
for (int i = 0; i != 10; ++i)
vec2.insert( vec2.end(), vec2[0] );
return 0;
}
问题是 push_back() 和 insert() 都通过引用获取新项目,并且当向量被重新分配以获得更多空间时,新项目在插入之前变得无效。
GCC 应该也有这个问题。我没有检查 Clang,但这取决于它使用的是哪个 STD 库。
MSVC2010 在 push_back() 中有一些额外的代码,用于检测新项目是否实际上是向量中的项目。如果是这样,它会记录项目的索引并在分配内存后使用它来插入项目(而不是使用现在无效的引用)——使用 _Inside(_STD addressof(_Val))
MSVC 的额外代码是非标准的吗?
我担心的是我不确定我可能在什么代码中做了类似 vec.push_back(vec[1]); 或 vec.insert(it, vec[2]); 我必须查看数百行甚至数千行使用 push_back 和 insert 的代码,这只是我自己的代码...... 3rd 方库也可能受到影响。
我假设使用这种技术可以使 GCC 以可怕的方式死亡(我没有看到额外的代码来处理这种情况,但 valgrind 在我的简单示例中没有检测到它,因此更难测试),
如何最好地检测和避免犯这个错误?
MSVC2010 的额外 push_back() 代码是非标准的吗?当 MSVC 发现以这种方式使用的向量时,是否应该改为检测并断言?(即安全计算倡议)
我正在考虑破解 MSVC2010 和 GCC 的标头来检测这些情况。
还有其他想法吗?
谢谢,保罗
PS:另请注意,如果您可以保证向量不需要调整大小,则此用法非常好(且有效)