Я запускаю программу с рекурсивным вызовом на ОС Debian. Размер моего стека
-s: stack size (kbytes) 8192
Насколько я понял, размер стека должен быть фиксированным и должен быть таким же, который должен быть выделен программе при каждом прогоне, если он явно не изменен с помощью ulimit
.
Рекурсивная функция уменьшает заданное число до тех пор, пока оно не достигнет 0
. Это написано в Rust.
fn print_till_zero(x: &mut i32) {
*x -= 1;
println!("Variable is {}", *x);
while *x != 0 {
print_till_zero(x);
}
}
и значение передается как
static mut Y: i32 = 999999999;
unsafe {
print_till_zero(&mut Y);
}
Поскольку стек, выделенный для программы, является фиксированным и теоретически не должен меняться, я ожидал, что переполнение стека будет с одним и тем же значением каждый раз, но это не так, что означает, что распределение стека является вариативным.
Запуск 1:
====snip====
Variable is 999895412
Variable is 999895411
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
Выполнить 2:
====snip====
Variable is 999895352
Variable is 999895351
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
Хотя разница тонкая, не должно ли это быть идеальным вызовом с той же переменной? Почему это происходит в разное время, подразумевая разные размеры стека для каждого прогона? Это не относится к Rust; аналогичное поведение наблюдается в C:
#pragma GCC push_options
#pragma GCC optimize ("O0")
#include<stdio.h>
void rec(int i){
printf("%d,",i);
rec(i-1);
fflush(stdout);
}
int main(){
setbuf(stdout,NULL);
rec(1000000);
}
#pragma GCC pop_options
Вывод:
Запуск 1:
738551,738550,[1] 7052 segmentation fault
Выполнить 2:
738438,738437,[1] 7125 segmentation fault