Значение, переданное ObjectPool::allocate
- это количество объектов, которые будут последовательно сохранены в памяти. Это означает, что когда вызывается allocator(2)
, вам необходимо вернуть указатель на блок, содержащий не менее 2 * sizeof(T)
блоков. Ваш распределитель возвращает только указатель на один блок. Когда векторный конструктор добавляет 2-й (или 3-й) элемент к вновь созданному вектору, он перезапишет память, которая не была специально назначена. Следующий вызов allocator
назначит эту память, что приведет к повреждению вашего вектора.
Выделенная память вектора является смежной. При первом вызове push_back
один элемент выделяется для вектора (который будет иметь емкость 1). Это сгенерирует строки 1-2 вашего вывода.
При втором вызове push_back
, поскольку емкость вектора заполнена, будет запрошен новый блок. Это генерирует строки 2-7 вашего вывода. Строка 4 копирует существующий элемент в новый блок памяти, строка 5 создает новый элемент, который был только что добавлен, строка 6 уничтожает этот элемент из исходного блока памяти. Строка 7 - это когда этот оригинальный блок памяти освобождается (возвращается распределителю). Емкость вектора будет равна 2.
Следующий вызов push_back
снова вызовет изменение размера вектора, генерируя строки 8-14 вашего вывода. Строки 9-10 копируют существующие элементы в новый блок памяти, 11 создают новый добавленный элемент, 12-13 уничтожают их в старом блоке памяти, а 14 возвращает старый блок памяти распределителю.
Вывод в следующих строках поврежден, потому что последующие вызовы вашего распределителя возвращают указатели в память, которую использует векторный объект. Копирование полученных данных перемещает неверные или поврежденные данные.
Решение состоит в том, чтобы ваша функция allocate
резервировала правильное количество блоков. (Таким образом, allocate(2)
должен продвинуться nextFreeItem
на два блока, предполагая, что два, которые он продвигает, являются смежными.)