9

This code gave me an error:

fn main() {
    let x = [0 as u64; std::u64::MAX as usize];
    println!("Hello, world! {}", std::u64::MAX);
}
error: the type `[u64; 18446744073709551615]` is too big for the current architecture
 --> src/main.rs:2:9
  |
2 |     let x = [0 as u64; std::u64::MAX as usize];
  |         ^
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
HelloWorld
  • 973
  • 2
  • 9
  • 23
  • 13
    Do you have 137 billion gigabytes of memory? Because that's how much you'd need for that array. – interjay Nov 06 '19 at 14:49
  • 8
    As the error suggests, the limit is of the "current architecture", not Rust. The default stack size is 2 MB, so you will get a stack overflow as soon as you run code that tries to instantiate an array of more than 2 million elements (actually 250,000 `u64`s). You will **never** be able to allocate as much as you are trying, even if you used (for example) a `Vec` to put it on the heap. – Peter Hall Nov 06 '19 at 14:50
  • I think the problem here is that you are specifying the *actual* size in memory that the OS will reserve for the array, not the *maximum size* . You might want to try a `Vec` if you don't know how long the array is going to be at compile time. – Coder-256 Nov 06 '19 at 15:14
  • @interjay, technically you could be required to have this amount of memory to host this array. But in reality using virtual memory tricks (like not actually initializing pages, until it's actually required; or swapping, but again, there're no known large storage devices for this) you may have it. And it will work, until it won't. Which is not `rust` way of doing thing, obviously. – user28434'mstep Nov 06 '19 at 15:19
  • 4
    @user28434 even using virtual memory tricks, you can't declare an array of this size because you can't address it, even with 64-bits pointers. – Jmb Nov 06 '19 at 15:40

1 Answers1

14

Array length is constrained by the isize type, which is a platform-sized integer:

The isize type is a signed integer type with the same number of bits as the platform's pointer type. The theoretical upper bound on object and array size is the maximum isize value. This ensures that isize can be used to calculate differences between pointers into an object or array and can address every byte within an object along with one byte past the end.

  • 16-bit platforms: A maximum value of 215 - 1
  • 32-bit platforms: A maximum value of 231 - 1
  • 64-bit platforms: A maximum value of 263 - 1
fn main() {
    let x = [(); std::isize::MAX];
    println!("Hello, world! {}", x.len());
}

Your specific error is because constructing an array of that many elements when the element has a non-zero size would require an outrageous amount of memory, more than a given platform would actually support.

An array's size is computed by the size of an element multiplied by the element count. Your array has elements of type u64 (8 bytes) and attempts to have 264 - 1 elements, totaling 147.6 exabytes.

On 64-bit Linux, with Rust 1.38, it appears that the maximum size is 247 - 1:

[0u8; (1usize << 47) - 1];
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    "On 64-bit Linux, with Rust 1.38, it appears that the maximum size is 2⁴⁷ - 1:" while you will be able to *compile* such a program, it will immediately segfault on any real machine because that's still a petabyte of memory. – mcarton Nov 06 '19 at 17:07
  • 2
    [This Nomicon chapter](https://doc.rust-lang.org/nomicon/vec-alloc.html) mentions "As such we must limit all allocations to `isize::MAX` elements". There are some more subtle limits in place, I think. That chapter mentions a lot of details about allocation limits. – Lukas Kalbertodt Nov 06 '19 at 18:11
  • 5
    FWIW, The reason it's 2^47 instead of 2^48 is because the address space is discontinuous, not related to the `isize`/`usize` issue (which would only be a concern if you could use the whole address space). [Canonical form addresses](https://en.m.wikipedia.org/wiki/X86-64#Virtual_address_space_details) – trent Nov 06 '19 at 18:24
  • @Shepmaster In the latest version of Rust(1.71.1), using `std::isize::MAX` will give a compile time error: `let x = [(); std::isize::MAX]; | ^^^^^^^^^^^^^^^ expected `usize`, found `isize``. An alternative to this can be either(depending on your choice): `let x : [(); 9223372036854775807] = [(); std::isize::MAX as usize];` or `let y : [(); 18446744073709551615] = [(); std::usize::MAX];` – imraklr Aug 08 '23 at 07:25