Максимальный размер массива в 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.