Максимальный размер массива в 32 битах?
В соответствии с Rust Reference:
Тип isize
представляет собой целочисленный тип со знаком с таким же количеством бит, что и тип указателя платформы. Теоретическая верхняя граница размера объекта и массива - это максимальное значение isize
. Это гарантирует, что isize
может использоваться для вычисления различий между указателями в объекте или массиве и может адресовать каждый байт внутри объекта вместе с одним байтом за конец.
Это явно ограничивает массив не более чем 2G-элементами в 32-битной системе, однако неясно, является ли массив также ограниченным объемом не более 2 ГБ памяти.
В C или С++ вы могли бы направить указатели на первый и один прошлый последний элемент на char*
и получить разницу указателей от этих двух; эффективно ограничивая массив до 2 ГБ (чтобы он не переполнял intptr_t
).
Является ли массив из 32 бит также ограниченным 2 ГБ в Rust? Или нет?
Ответы
Ответ 1
Внутренние элементы Vec
делают ограничение на 4 ГБ, как в with_capacity
, так и grow_capacity
, используя
let size = capacity.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
который будет паниковать, если указатель переполняется.
Таким образом, Vec
-распределенные срезы также ограничены таким образом в Rust. Учитывая, что это связано с основным ограничением в API распределения, я был бы удивлен, если бы какой-либо типичный тип мог обойти это. И если они это сделают, Index
на срезах будет небезопасным из-за переполнения указателя. Поэтому я надеюсь, что нет.
Однако, по-прежнему, возможно, не удастся выделить все 4 ГБ по другим причинам. В частности, allocate
не позволит вам выделить более 2 ГБ (isize::MAX
байты), поэтому Vec
ограничивается этим.
Ответ 2
Rust использует LLVM в качестве компилятора. Команда LLVM для арифметики указателя (GetElementPtr
) принимает смещенные целочисленные смещения и имеет поведение undefined при переполнении, поэтому невозможно индексировать массивы размером более 2 ГБ при ориентации на 32-битную платформу.
Чтобы избежать поведения undefined, Rust откажется выделить более 2 ГБ в одном распределении. Подробнее см. Статью Rust # 18726.