【问题标题】:Thread '<main>' has overflowed its stack when allocating a large array using Box使用 Box 分配大型数组时,线程 '<main>' 已溢出其堆栈
【发布时间】:2020-07-01 18:48:00
【问题描述】:

我正在实施combsort。我想在堆栈上创建固定大小的数组,但它显示stack overflow。当我将它更改为在堆上时(Rust by Example 说to allocate in the heap we must use Box),它仍然显示stack overflow

fn new_gap(gap: usize) -> usize {
    let ngap = ((gap as f64) / 1.3) as usize;
    if ngap == 9 || ngap == 10 {
        return 11;
    }
    if ngap < 1 {
        return 1;
    }
    return ngap;
}

fn comb_sort(a: &mut Box<[f64]>) {
    // previously: [f64]
    let xlen = a.len();
    let mut gap = xlen;
    let mut swapped: bool;
    let mut temp: f64;
    loop {
        swapped = false;
        gap = new_gap(gap);
        for i in 0..(xlen - gap) {
            if a[i] > a[i + gap] {
                swapped = true;
                temp = a[i];
                a[i] = a[i + gap];
                a[i + gap] = temp;
            }
        }
        if !(gap > 1 || swapped) {
            break;
        }
    }
}

const N: usize = 10000000;

fn main() {
    let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
    for z in 0..(N) {
        arr[z] = (N - z) as f64;
    }
    comb_sort(&mut arr);
    for z in 1..(N) {
        if arr[z] < arr[z - 1] {
            print!("!")
        }
    }
}

输出:

thread '<main>' has overflowed its stack
Illegal instruction (core dumped)

或者

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

我知道我的堆栈大小不够,与C++在函数内部创建太大的非堆数组时相同,但是这段代码使用堆但仍然显示堆栈溢出。这段代码到底有什么问题?

【问题讨论】:

  • 我应该无耻地插入一个我为解决这个特定问题而构建的板条箱:crates.io/crates/arr - 我一直在努力寻找一个干净的解决方案来解决这个问题。

标签: rust heap-memory dynamic-memory-allocation


【解决方案1】:

据我所知,该代码似乎仍在尝试先在堆栈上分配数组,然后再将其移入框内。

如果我像这样切换到Vec&lt;f64&gt; 代替Box&lt;[f64]&gt;,它对我有用:

fn new_gap(gap: usize) -> usize {
    let ngap = ((gap as f64) / 1.3) as usize;
    if ngap == 9 || ngap == 10 {
        return 11;
    }
    if ngap < 1 {
        return 1;
    }
    return ngap;
}

fn comb_sort(a: &mut [f64]) {
    // previously: [f64]
    let xlen = a.len();
    let mut gap = xlen;
    let mut swapped: bool;
    let mut temp: f64;
    loop {
        swapped = false;
        gap = new_gap(gap);
        for i in 0..(xlen - gap) {
            if a[i] > a[i + gap] {
                swapped = true;
                temp = a[i];
                a[i] = a[i + gap];
                a[i + gap] = temp;
            }
        }
        if !(gap > 1 || swapped) {
            break;
        }
    }
}

const N: usize = 10000000;

fn main() {
    let mut arr: Vec<f64> = std::iter::repeat(0.0).take(N).collect();
    //let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
    for z in 0..(N) {
        arr[z] = (N - z) as f64;
    }
    comb_sort(arr.as_mut_slice());
    for z in 1..(N) {
        if arr[z] < arr[z - 1] {
            print!("!")
        }
    }
}

【讨论】:

  • 检查 LLVM IR 的 smaller example 显示:alloca [10000000 x double], align 8,所以我相信您是正确的 - 数组首先分配在堆栈上。
【解决方案2】:

未来,box 语法将会稳定。如果是,它将支持这种大分配,因为不需要对Box::new 的函数调用,因此数组永远不会放在堆栈上。例如:

#![feature(box_syntax)]

fn main() {
    let v = box [0i32; 5_000_000];
    println!("{}", v[1_000_000])
}

【讨论】:

    猜你喜欢
    • 2017-04-18
    • 2016-05-07
    • 2015-04-23
    • 2011-05-16
    • 1970-01-01
    • 2016-09-22
    • 2020-05-24
    • 2015-05-08
    相关资源
    最近更新 更多