Как установить размер стека потоков во время компиляции?

При попытке запустить программу, которая создает большую clap::App (найти источник здесь), Я получаю stackoverflow: thread '<main>' has overflowed its stack.

До сих пор мне не удалось выяснить, как проинструктировать rustc увеличить стекирование для обходного пути грубой силы. RUST_MIN_STACK, похоже, применим только к времени выполнения, и даже там он, похоже, не имеет никакого эффекта.

Когда код сгенерирован, мне, вероятно, придется переместить создание SubCommand во время выполнения, что я и попытаюсь сделать дальше.

Однако вы видите способ исправить это по-другому?

Похоже, что это важно, поскольку шаблоны построек, похоже, склонны к этой проблеме, если построенная структура просто большая и достаточно вложенная.

Как воспроизвести

git clone -b clap https://github.com/Byron/google-apis-rs
cd google-apis-rs
git checkout 9a8ae4b
make dfareporting2d1-cli-cargo ARGS=run

Обратите внимание, что вам понадобится вилка quasi и установите локальное переопределение, чтобы разрешить создание с помощью последнего компилятора.

Meta​​h1 >

➜  google-apis-rs git:(clap) rustc --version
rustc 1.1.0-nightly (97d4e76c2 2015-04-27) (built 2015-04-28)

Ответ 1

Невозможно установить размер стека основного потока в Rust. Фактически, предположение о размере стека основного потока выполняется на уровне исходного кода в библиотеке Rust runtime (https://github.com/rust-lang/rust/blob/master/src/libstd/rt/mod.rs#L85).

Переменная окружения RUST_MIN_STACK влияет на размер стека потоков, созданных в программе, а не на основной поток, но вы также можете легко указать это значение в исходном коде во время выполнения.

Самый простой способ решить вашу проблему может заключаться в том, чтобы запустить clap в отдельном потоке, который вы создаете, чтобы вы могли контролировать размер его стека.

Возьмите этот код, например:

extern crate clap;
use clap::App;
use std::thread;

fn main() {
    let child = thread::Builder::new().stack_size(32 * 1024 * 1024).spawn(move || {
        return App::new("example")
            .version("v1.0-beta")
            .args_from_usage("<INPUT> 'Sets the input file to use'")
            .get_matches();
    }).unwrap();

    let matches = child.join().unwrap();

    println!("INPUT is: {}", matches.value_of("INPUT").unwrap());
}

clap, похоже, может правильно завершить приложение из дочернего потока, поэтому ваш код должен работать с небольшими изменениями.