смущен максимальным размером std::вектор

#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
 

У меня есть два вопроса по этому поводу:

  1. Почему максимальное значение так мало? это похоже на максимум uint32. Я ожидал, что он будет больше в диапазоне size_t, который должен быть 18446744073709551615, верно?
  2. Почему я получаю 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_size

3. Вы используете «%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). Это определенно не проблема с оперативной памятью.