このコードを 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(それ、vec[2]); push_back と insert を使用する数千行ではないにしても、数百行のコードを調べる必要があります。これは単なる私自身のコードです... サードパーティのライブラリも影響を受ける可能性があります。
この手法を使用すると、GCC が恐ろしい方法で停止する可能性があると思います (このケースを処理するための追加のコードはありませんが、valgrind は私の単純な例ではそれを検出しなかったため、テストが難しくなります)、
この間違いを検出して回避するにはどうすればよいでしょうか?
MSVC2010 の余分な push_back() コードは非標準ですか? MSVC は代わりに、この方法で使用されているベクトルを検出してアサートする必要がありますか? (つまり、セキュア コンピューティング イニシアチブ)
これらのケースを検出するために、MSVC2010 と GCC のヘッダーをハッキングすることを考えています。
他のアイデアはありますか?
ありがとう、ポール
PS: ベクトルのサイズを変更する必要がないことを保証できる場合、この使用法は完全に問題なく (そして効率的) であることにも注意してください。