2015-09-01 38 views
10

Theo Rust Reference:Kích thước tối đa của một mảng trong 32 bit?

Các isize type là một kiểu số nguyên ký kết với cùng một số bit như kiểu con trỏ của nền tảng. Giới hạn trên lý thuyết trên đối tượng và kích thước mảng là giá trị tối đa isize. Điều này đảm bảo rằng isize có thể được sử dụng để tính toán sự khác biệt giữa các con trỏ vào một đối tượng hoặc mảng và có thể giải quyết mọi byte trong một đối tượng cùng với một byte qua kết thúc.

Điều này rõ ràng ràng buộc một mảng ở hầu hết các phần tử 2G trên hệ thống 32 bit, tuy nhiên điều không rõ là liệu mảng có bị hạn chế tối đa 2GB bộ nhớ hay không.

Trong C hoặc C++, bạn có thể truyền con trỏ đến phần tử đầu tiên và một trong quá khứ cuối cùng đến char* và thu được sự khác biệt của con trỏ từ hai phần tử đó; có hiệu quả hạn chế mảng đến 2GB (vì sợ rằng nó tràn intptr_t).

Có phải mảng trong 32 bit cũng bị giới hạn ở mức 2 GB trong Rust không? Hay không?

Trả lời

5

Các bên trong của Vec làm cap giá trị đến 4GB, cả trong with_capacitygrow_capacity, sử dụng

let size = capacity.checked_mul(mem::size_of::<T>()) 
        .expect("capacity overflow"); 

mà sẽ hoảng sợ nếu tràn con trỏ.

Vì vậy, Vec lát cắt lát cũng được giới hạn theo cách này trong Rust. Cho rằng điều này là do một hạn chế cơ bản trong API phân bổ, tôi sẽ ngạc nhiên nếu bất kỳ loại điển hình nào có thể phá vỡ điều này. Và nếu họ đã làm, Index trên lát sẽ không an toàn do tràn con trỏ. Vì vậy, tôi hy vọng là không.

Mặc dù vậy, vẫn không thể phân bổ tất cả 4GB vì các lý do khác. Cụ thể, allocate sẽ không cho phép bạn phân bổ nhiều hơn 2GB (isize::MAX byte), do đó, Vec bị hạn chế.

+0

Vì vậy, câu trả lời là: có điều này được giới hạn ở mức 2GB không? –

+0

@MatthieuM. Vâng. Tôi đã chỉnh sửa câu trả lời của mình để có một chút rõ ràng hơn về điều này. – Veedrac

+1

'dung lượng' là' sử dụng 'trong cả hai phương pháp, do đó dung lượng tối đa của một' Vec' sẽ là 4GB. Tuy nhiên, người cấp phát có thể thất bại nếu kích thước phân bổ được yêu cầu vượt quá 2GB ... –

2

Rust sử dụng LLVM làm trình biên dịch phụ trợ. Lệnh LLVM cho số học con trỏ (GetElementPtr) mất số nguyên đã ký và có hành vi không xác định trên tràn, vì vậy không thể lập chỉ mục thành các mảng lớn hơn 2GB khi nhắm mục tiêu nền tảng 32 bit.

Để tránh hành vi không xác định, Rust sẽ từ chối phân bổ nhiều hơn 2 GB trong một phân bổ đơn lẻ. Xem Vấn đề về Rust #18726 để biết chi tiết.

+1

Tôi đã kiểm tra lỗi và Câu hỏi thường gặp của GEP và giới hạn không phải là vấn đề về bộ nhớ mà là số lượng phần tử: khi bạn chuyển 'i32 1' sang GEP nó theo từng phần tử, vì vậy với 4 byte yếu tố, nó có thể giải quyết 4 GB mảng dễ dàng. Lưu ý rằng ví dụ cụ thể về 'Vec ' là một phần tử 1 byte, do đó giới hạn 2GB cho ví dụ này. –

Các vấn đề liên quan