Доступ к необработанному указателю после std::vector:: резервный сейф?
Это довольно надуманный, но следующий код "безопасен" (т.е. гарантированно не вызывает ошибку сегментации):
std::vector<int> vec(1); // Ensures that &vec[0] is valid
vec.reserve(100);
memset(&vec[0], 0x123, sizeof(int)*100); // Safe?
Я понимаю, что это уродливо - мне только интересно узнать, технически ли это безопасно, а не "красиво". Я предполагаю, что его единственным использованием может быть игнорирование значений, хранящихся за пределами данного индекса.
Внимание! Как я могу получить адрес буфера, выделенного vector:: reserve()?, охватывает ту же тему, но меня больше интересует, если это безопасно, и если это подводные камни, делающие это.
EDIT: Исходный код был неправильным, заменил оригинал memcpy
на memset
.
Ответы
Ответ 1
Нет, это не безопасно.
После a reserve()
, вектор гарантированно не перераспределяет хранилище до достижения capacity()
.
Однако стандарт не говорит, что векторная реализация может выполнять с хранилищем между size()
и capacity()
. Возможно, это может быть использовано для некоторых внутренних данных - кто знает? Возможно, адресное пространство просто зарезервировано и не отображено в реальном ОЗУ?
Доступ к элементам за пределами [0..размер] - это поведение undefined. Для этого может быть какая-то аппаратная проверка.
Ответ 2
Вектор-перераспределение делает недействительными указатели существующих, ссылки и т.д. Резерв может запускать перераспределение (23.3.6.2, [vector.capacity]), но вы берете адрес первый элемент после возможного перераспределения (что в этом случае, вероятно, не произойдет вообще, но это помимо точки). Поэтому я не вижу проблем с кодом.
Ответ 3
Прежде всего обратите внимание, что ваш memset
обрезает 0x123
в один байт и напишет это, не записывая четырехбайтовый шаблон.
Тогда не делайте этого, просто используйте контейнер: std::vector<int> vec(100, whatever_value_you_want);
Однако для ответа на вопрос он может работать специально для типов POD, если компилятор не использует выделенное пространство для чего-либо. Конечно, если кто-либо называет resize
, insert
, push_back
и т.д., Он сдует все, что вы уже записали в память, и размер вектора также будет неправильным. Там просто нет причин писать такой код.