#c #stdvector #integer-overflow
Вопрос:
Я столкнулся с проблемой в своем коде с помощью std::vector, которая дала мне: vector<T> too long
. В данном случае я использую вектор символов. Код обрабатывает 3D (томографические) изображения, поэтому у меня много вокселов. У меня точно такая же проблема в Windows с использованием компилятора VS, что и на Mac с использованием CLANG, еще не протестированного gcc.
Чтобы проверить проблему, я добавил следующие строки:
printf("max vector size %un", v.max_size() );
printf("PTRDIFF_MAX %u, INTMAX_MAX %un", PTRDIFF_MAX, INTMAX_MAX );
Что дало мне:
max vector size 4294967295
PTRDIFF_MAX 4294967295, INTMAX_MAX 4294967295
У меня есть два вопроса по этому поводу:
- Почему максимальное значение так мало? это похоже на максимум uint32. Я ожидал, что он будет больше в диапазоне size_t, который должен быть 18446744073709551615, верно?
- Почему я получаю
vector<T> too long
, когда мой вектор превышает 2147483648 (т. Е. половину заявленного максимального) числа значений?
[править]
Некоторые ответы:
- Спасибо, что указали на мои ошибки в печати. Я преобразовал в std::cout, и теперь я получаю (что имеет больше смысла в 64-битной системе):
max_size: 9223372036854775807 PTRDIFF_MAX: 9223372036854775807 INTMAX_MAX: 9223372036854775807
- Эта ошибка
vector<T> too long
является ошибкой во время выполнения - Я проследил его до линии, где я изменяю размер вектора
- Когда я использую вектор uint32_t вместо символа, проблема возникает при той же длине вектора (при использовании памяти в 4 раза больше).
- У меня более чем достаточно оперативной памяти, однако я не знаю, как работает распределение при запросе на изменение размера. Возможно, нет достаточно большого непрерывного блока оперативной памяти?
Комментарии:
1. Что это тебе дает
vector<T> too long
? Пожалуйста, предоставьте код, демонстрирующий эту проблему.2. @Jann5s
max_size
-это теоретический предел (на самом деле он может быть меньше, например, из-за доступной оперативной памяти), и он определяется реализацией: en.cppreference.com/w/cpp/container/vector/max_size3. Вы используете «%u». Это есть
unsigned int
, но вы проходитеstd::vector<T>::size_type
, этого не нужно бытьunsigned int
. Ваше ожидание выходных значений 4294967295 с «%u» неверно.4. Используйте потоки iostreams C вместо библиотеки C, чтобы удобно избежать проблем с преобразованием. Я получаю 4611686018427387903 для
max_size()
и 9223372036854775807 с двумя другими на моем Mac с лязгом.5. Обратите внимание, что
max_size
это не обещание, а теоретический максимум. Фактический максимум зависит от размера элементов и доступной памяти. Возможно, у вас нет2147483648 * 2 * sizeof(T)
доступной непрерывной памяти в дополнение к текущим элементам 2147483648..
Ответ №1:
Почему максимальное значение так мало? это похоже на максимум uint32.
Этого следует ожидать в 32-разрядных системах.
Я ожидал, что он будет больше в диапазоне size_t, который должен быть 18446744073709551615, верно?
Если PTRDIFF_MAX
это 4294967295, то я нахожу удивительным, что SIZE_MAX
это будет целых 18446744073709551615. Тем не менее, я бы также счел, что это превосходит то, что PTRDIFF_MAX
было 4294967295.
Вы видите неожиданный и бессмысленный вывод, потому что поведение программы не определено, что связано с тем, что вы использовали неправильный спецификатор формата. %u
предназначен для unsigned int и только для unsigned int. %td
спецификатор предназначен для std::ptrdiff_t
, PRIdMAX
макрос расширяется до спецификатора для std::intmax_t
и %zu
предназначен для std::size_t
.
Я рекомендую научиться использовать потоки iostreams C . С их помощью не так просто случайно вызвать неопределенное поведение, как при использовании стандартного ввода-вывода C.
Почему я получаю слишком длинный вектор, когда мой вектор превышает 2147483648 (т. Е. половину заявленного максимального) числа значений?
Я не знаю, что значит «слишком длинный вектор», но обычно у вас нет всего адресного пространства, доступного для вашей программы. Вполне возможно, что половина его зарезервирована для ядра.
max_size
не обязательно учитывает такие системные ограничения и является теоретическим пределом, который обычно не достижим на практике.
Комментарии:
1. Спасибо вам (и комментаторам выше) за то, что указали на мою ошибку с printf. Я преобразовал в std::cout и теперь я получаю: max_size: 9223372036854775807 PTRDIFF_MAX: 9223372036854775807 INTMAX_MAX: 9223372036854775807, который выглядит для меня как предел int64. Это я понимаю, потому что я на 64-битной системе. Это все еще оставляет вопрос, почему размер моего вектора не может превышать 2*10^9 элементов (типа char). Это определенно не проблема с оперативной памятью.