【问题标题】:Am getting "Illegal instruction" when running collect on iter::count在 iter::count 上运行 collect 时收到“非法指令”
【发布时间】:2014-12-27 06:25:01
【问题描述】:

运行这个:

fn main() {
    std::iter::count(1i16, 3).collect::<Vec<i16>>();
}

我明白了:

线程''在'容量溢出'时恐慌,/home/tshepang/projects/rust/src/libcore/option.rs:329

这就是我在运行它时所期望的:

fn main() {
    std::iter::count(1i8, 3).collect::<Vec<i8>>();
}

但是,我得到了这个:

非法指令

另外,syslog 会显示这一行:

12 月 27 日 08:31:08 thome 内核:[170925.955841] 陷阱:main[30631] 陷阱无效操作码 ip:7f60ab175470 sp:7fffbb116578 错误:0 in main[7f60ab15c000+5b000]

【问题讨论】:

  • std::iter::count 生成无限的项目集,然后您将无限列表放入Vector。这是您的实际目标,还是只是在探索失败案例?
  • 我只是好奇会发生什么,所以是的,你可以说我只是在探索失败案例。

标签: linux rust


【解决方案1】:

这是一次有趣的冒险。

Iter::collect 只是调用FromIterator::from_iter

Vec's implementation of FromIterator 向迭代器询问其大小,然后分配内存:

let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower);

Vec::with_capacity 计算内存的总大小并尝试分配它:

let size = capacity.checked_mul(mem::size_of::<T>())
               .expect("capacity overflow");
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
if ptr.is_null() { ::alloc::oom() } // Important!

在这种情况下,i8 占用 1 个字节,无限迭代器的下限是std::uint::MAX。相乘,仍然是std::uint::MAX。当我们分配它时,我们得到一个空指针。

alloc::oom 被定义为简单中止,这是通过非法指令实现的!

i16 具有不同行为的原因是因为它触发了checked_mul 期望——你不能分配std::uint::MAX * 2 字节!


在现代 Rust 中,示例会写成:

(1i16..).step_by(3).collect::<Vec<_>>();
(1i8..).step_by(3).collect::<Vec<_>>();

现在两者都以相同的方式失败:

memory allocation of 12297829382473034412 bytes failed
memory allocation of 6148914691236517206 bytes failed

【讨论】:

  • 这个Illegal instruction 也会发生在 Windows 上吗?
  • 在 Windows 上,您会看到“foo.exe 已停止工作”弹出对话框。
猜你喜欢
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多