gpt4 book ai didi

c - 为什么每次运行时堆栈使用量不同而不是固定数量时会发生堆栈溢出?

转载 作者:IT王子 更新时间:2023-10-29 00:10:38 27 4
gpt4 key购买 nike

我正在 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

最佳答案

这很可能是由于 ASLR .

堆栈的基地址在每次运行时都是随机的,使某些类型的漏洞利用更加困难;在 Linux 上这个 has a granularity of 16 bytes (这是 x86 和我所知道的几乎所有其他平台上最大的对齐要求)。

另一方面,the page size is (normally) 4 KB on x86 ,当你触摸第一个禁止页面时,系统检测到堆栈溢出;这意味着在系统检测到堆栈溢出之前,您总是首先有一个可用的部分页面(偏移量取决于 ASLR),然后是两个完整页面。因此,总的可用堆栈大小至少是您请求的 8192 字节加上第一个部分页面,其可用大小在每次运行时都不同。1


  1. 所有这些都是在偏移量非零的“常规”情况下;如果您非常幸运并且随机偏移量为零,您可能正好得到两页。

关于c - 为什么每次运行时堆栈使用量不同而不是固定数量时会发生堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42993387/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com