为什么Rust会对 `[u8; isize::MAX as usize / 4 + 1]` 报错,尽管理论上的分配上限是 `isize::MAX`?
下面给出一个可复现的示例:
fn main() {
let _: [u8; isize::MAX as usize / 4];
let _: [u8; isize::MAX as usize / 4 + 1];
let _a: [u8; isize::MAX as usize / 4];
let _b: [u8; isize::MAX as usize / 4 + 1];
}
它因以下错误而失败:
error: values of the type `[u8; 2305843009213693952]` are too big for the target architecture
--> src/main.rs:6:9
|
6 | let _b: [u8; isize::MAX as usize / 4 + 1];
| ^^
error: could not compile `lab` (bin "lab") due to 1 previous error
这让我想知道:
- 具体是什么原因导致这个错误?
- 这个行为有文档说明吗?
- 为什么第3行会被接受?
解决方案
这是一个技术性限制。LLVM使用64位整数来表示对象大小,单位为位。这为以字节表示的大小留出了61位空间。因此对于基于LLVM的实现,对象的大小不能超过2^61-1字节。
我在文档中没有找到这一点,但这个限制在 rustc源代码 中是存在的。
这个数字在2024年从2^47提升到了2^61。
这行
let _: [u8; isize::MAX as usize / 4 + 1];
在本地被认为是一个空操作(no-op),也许这就是它被接受的原因。编译器并不需要实际创建对象,因此不需要检查大小,不管后续程序如何。
这行
let _a: [u8; isize::MAX as usize / 4];
之所以被接受,是因为大小正好是2^61-1字节。
在实际应用中,对象的大小不能超过硬件所支持的地址空间大小,对于英特尔硬件而言通常是2^57字节。超过该极限很可能导致运行时错误,而不是编译时错误(如果相关对象没有被完全优化掉)。
对象在栈上的实际大小要比那时小得多,但那样也会导致运行时错误。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。