데비안 OS에서 재귀 호출이있는 프로그램을 실행 중입니다. 내 스택의 크기는 지금까지 내가 배운대로, 스택 크기가 고정되어 있어야합니다고정 된 금액 대신 각각의 스택 사용에 따라 스택 오버플로가 발생하는 이유는 무엇입니까?
-s: stack size (kbytes) 8192
이며, 명시 적으로 ulimit
으로 변경하지 않는 한 모든 실행에서 프로그램에 할당해야하는 동일해야합니다.
재귀 함수는 0
에 도달 할 때까지 주어진 숫자를 감소시킵니다. 이것은 녹서에 기록되어 있습니다.
fn print_till_zero(x: &mut i32) {
*x -= 1;
println!("Variable is {}", *x);
while *x != 0 {
print_till_zero(x);
}
}
및 값 I가 동일한 값마다의 스택 오버 플로우를 예상하고, 변경 안 이론적
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
차이는 미묘하지만, 그것은 동일한 변수의 스택 오버 플로우를 일으키는 적이어야한다? 서로 다른 시간에 왜 그런 일이 일어나며, 각 실행마다 다른 스택 크기를 암시합니까? 이것은 녹과 관련이 없습니다. 비슷한 동작은 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