私はDebian OS上で再帰呼び出しを持つプログラムを実行しています。私のスタックサイズは、私の知る限り学んだように、スタックサイズが固定されている必要があり固定量ではなく、実行ごとにスタック使用量が異なると、スタックオーバーフローが発生するのはなぜですか?
-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
スタックオーバーフローは、ページ違反時にのみ発生します。スタックポインタがアンロードされた/未所有のページに実行されたときです。スタックの開始位置は正確なページ境界である必要はなく、プログラムがロードされる場所に依存するので、オーバーフロー条件(ページフォールト)のトリガーは異なります。 –
[this](http://stackoverflow.com/questions/31180563/why-are-stackoverflow-errors-chaotic)も同様ですか? – Art
@RichardCrittenしたがって、割り当てられたスタックサイズ外のページは、所有されていないページの権利でなければなりません。私が間違っているなら、私を修正してください。 – nohup