为什么在不存储结果的情况下两次调用Box :: new却分配了相同的堆地址?

时间:2019-12-17 02:26:12

标签: memory-management rust

我有以下代码段:

fn test() {
    let addr = Box::new(1024);
    println!("{:p}", addr);
}

fn main(){
    test();
    test();
}
0x7fd2fa402b70
0x7fd2fa402b70

如文档所述,Box::new将在堆上分配内存,然后将参数放入其中。无论我调用test()多少次,程序都会打印相同的地址。

即使代码在unsafe块中,Rust为什么也分配相同的堆地址?这是正常行为吗?

1 个答案:

答案 0 :(得分:6)

由于您没有将结果存储在test函数之外,因此分配的内存将立即释放。这样,内存分配器就可以在第二次调用之前重用相同的地址。


  

我认为当前的Box::new实现与我期望的行为不同

是的,这似乎有可能,但是值得考虑为什么为什么这种特定行为。对我来说,表现出来的行为是有道理的。

  

或者至少我们应该在[Box es] rustdoc上评论此“优化”

无论如何,这不是对Box的优化。没有所有者时立即释放值的行为是Rust语言定义的一部分。

可以将其视为当前正在使用的基础内存分配器的优化。但是,分配器实现对于许多程序员来说都是有意义的,并且不是Rust独有的。例如,这是C中类似的程序:

#include <stdio.h>
#include <stdlib.h>

int main() {
  for (int i = 0; i < 10; i++) {
    int32_t *v = malloc(sizeof(int32_t));
    printf("%p\n", (void *)v);
    free(v);
  }
}
% clang -std=c17 -Wpedantic -Wall alloc.c
% ./a.out
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860
0x7f87c6401860

请注意,内存分配器的实现最终导致返回相同的地址。有可能在不正确的地方编写一个内存分配器。