Поместите этот код в MS Visual С++ 2010, скомпилируйте (debug или release) и он выйдет из строя для цикла 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, и это только мой собственный код... Также могут быть затронуты и сторонние библиотеки.
Я предполагаю, что GCC можно было умереть ужасно, используя эту технику (я не вижу лишнего кода для обработки этого случая, но valgrind не обнаружил его в моем простом примере, поэтому будет труднее протестировать),
Как лучше всего обнаружить и избежать этой ошибки?
Является ли MSVC2010 дополнительным push_back() кодом нестандартным? Должен ли MSVC обнаруживать и утверждать, когда он находит векторы, используемые таким образом? (т.е. инициатива с защищенными вычислениями)
Я собираюсь взломать заголовки MSVC2010 и GCC для обнаружения этих случаев.
любые другие идеи?
Спасибо, Пол
PS: обратите внимание также, что это использование отлично (и эффективно), если вы можете гарантировать, что вектор не нужно изменять размер