将此代码放入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;
}
Run Code Online (Sandbox Code Playgroud)
问题是push_back()和insert()都通过引用获取新项目,并且当向量重新分配更多空间时,新项目在插入之前变为无效.
海湾合作委员会也应该有这个问题.我没有检查过Clang,但它取决于它使用的是哪个STD库.
MSVC2010在push_back()中有一些额外的代码,用于检测新项目是否实际上是向量中的项目.如果是这样,它会记录项目的索引,并在分配内存后使用它来插入项目(而不是使用现在无效的引用) - 使用_Inside(_STD addressof(_Val))
MSVC的额外代码是非标准的吗?
我担心的是我不知道我用什么代码做过像vec.push_back(vec [1])这样的代码; 或vec.insert(it,vec [2]); 我必须查看使用push_back和insert的数百行代码,这只是我自己的代码......第三方库也可能受到影响.
我假设GCC可以使用这种技术以可怕的方式死亡(我看到没有额外的代码来处理这种情况,但是valgrind在我的简单示例中没有检测到它因此将更难测试),
如何最好地检测并避免犯这个错误?
MSVC2010的额外push_back()代码是非标准的吗?当MSVC找到以这种方式使用的向量时,它应该检测并断言吗?(即安全计算计划)
我正在考虑攻击MSVC2010和GCC的标题以检测这些情况.
还有其他想法吗?
谢谢,保罗
PS:请注意,如果您可以保证向量不需要调整大小,则此用法非常精确(且高效)
为什么编译器不抱怨这段代码:
#include <string>
#include <iostream>
int main()
{
std::string a;
a = 2.3;
std::cout << "A:" << a << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会,MSVC似乎根本不关心这一点,即使它显然是错误的,但实际上并没有起作用!
输出是:
A:
Run Code Online (Sandbox Code Playgroud)
哦!导致程序中出现未检测到的错误.