为何派生线程中创建的Box拥有栈地址特征的高地址?
问题
在派生线程中创建Box时,Box的地址数值极高,具备栈地址的典型特征,但Box本应指向堆内存。为何该地址会如此之高?
代码
use std::thread; use std::time::Duration; fn main() { let x = 42; println!("x (main thread, stack): {:p}", &x); println!("Box (main thread, heap): {:p}", Box::new(x)); thread::spawn(|| { let x = 42; println!("x (spawned thread, stack): {:p}", &x); println!("Box (spawned thread, heap): {:p}", Box::new(x)); }); thread::sleep(Duration::from_secs(1)); // Give the spawned thread some time }
输出
x (main thread, stack): 0x7fff1d0cb414 Box (main thread, heap): 0x55e608db8ae0 x (spawned thread, stack): 0x7f94ae707b54 Box (spawned thread, heap): 0x7f94a8000b80
环境
- Linux
- cargo 1.69.0
- rustc 1.69.0
回答
这一现象的核心原因是Linux的地址空间随机化(ASLR) 以及内存分配器的线程本地优化策略,具体拆解如下:
地址数值高低不能作为栈/堆的绝对判断标准
Linux系统会通过ASLR随机化进程所有内存区域的起始地址,包括栈、堆、共享库、匿名映射区等。传统认知中“堆低地址、栈高地址”的布局只是未开启ASLR时的默认情况,开启ASLR后,堆的地址完全可能出现在高地址区间,和栈地址范围重叠。派生线程的内存分配来自高地址的匿名映射区
Rust默认使用的内存分配器(Linux下通常是glibc的ptmalloc或jemalloc)会为每个线程维护本地内存缓存,以减少多线程分配时的锁竞争。这些线程本地缓存的内存块通常通过mmap系统调用在高地址的匿名映射区分配,而非使用主线程初始的低地址堆空间。
从输出地址来看,派生线程的Box地址0x7f94a8000b80确实位于其栈地址0x7f94ae707b54的下方(栈是向下增长的),但这片内存属于进程的堆/匿名映射区域,并非栈空间。验证方式
你可以通过查看进程的内存映射文件/proc/[进程ID]/maps,找到0x7f94a8000b80所在的区域,会看到该地址对应的是anon_inode:[heap]或匿名映射类型,而非栈标记的[stack]。
内容的提问来源于stack exchange,提问作者dminuoso
相关产品推荐
相关产品推荐

