【问题标题】:How to tell if something is heap or stack allocated?如何判断某个东西是堆分配的还是堆栈分配的?
【发布时间】:2015-07-21 08:08:53
【问题描述】:

我想知道是否有办法确定变量是堆栈分配的还是堆分配的。

考虑一下:

struct SomeStruct;

fn main() {
    let some_thing = Box::new(SomeStruct);
    println!("{:p}", some_thing);
    foo(&*some_thing);
}

fn foo (bar: &SomeStruct) {
    println!("{:p}", bar);
}

打印

0x1
0x1

然后

struct SomeStruct;

fn main() {
    let some_thing = &SomeStruct;
    println!("{:p}", some_thing);
    foo(some_thing);
}

fn foo (bar: &SomeStruct) {
    println!("{:p}", bar);
}

打印

0x10694dcc0
0x10694dcc0

我可以看到堆分配版本的内存地址要短得多,但我不知道这是否是区分差异的可靠方法。不知道有没有类似std::foo::is_heap_allocated()

【问题讨论】:

  • 首先想到的问题是“为什么?”。有了这些知识,什么样的代码会有不同的工作方式?
  • 我不需要这段代码来比更多地发现语言:)
  • 0x1 是 Rust 分配器为零大小对象返回的虚拟地址,它不在堆上。见heap.rs#L90
  • 我也有同样的问题。我想知道,因为我感兴趣的是这件事是如何在幕后工作的。例如,这个简单的例子似乎显示了几乎连续地址 play.rust-lang.org/… 中的所有内容。我现在想知道是否所有对堆的引用都占用了堆栈空间,它给了我对堆的堆栈引用的地址。
  • @MrMesees 所有地址都是连续的,因为您只获取(和打印)堆栈地址:numdog 在堆栈上,zoo 是一个数组,因此它存在堆栈,虽然Vec 的“存储缓冲区”是堆分配的,但您只打印 Vec 结构本身的地址(指针、长度和容量的三元组),并且在堆栈上.

标签: rust heap-memory stack-memory


【解决方案1】:

如果您在某个 POSIX 系统上,您可能可以使用带有 0 参数的 sbrk() 系统调用来确定程序中断的当前位置,即堆的当前限制。如果给定值的地址小于此地址但大于堆的开头,则它在堆上。我不知道你会如何检查它是否在堆栈上,这不一定会自动选择不在堆上,因为它也可以是静态初始化或未初始化的数据,尽管这可能很明显您在检查代码时。您可能可以在 x86_64 架构上使用rbp 寄存器,它应该指向当前堆栈帧的开头。如果您想检查它是否在当前堆栈帧上,或者如果您想检查它是否在堆栈上的任何位置,您可以使用rsp

我认为您可以使用 end() 系统调用使用 end 参数来启动堆。所以堆的下限是end(end)的结果,上限是sbrk(0)

【讨论】:

  • 大多数现代 POSIX 系统(/分配器)使用mmap 而不是(s)brk 来获取堆空间。 (s)brk 在 macOS 上被正式弃用(将触发警告),并且在大多数 BSD 上都被非正式地弃用(它们被称为“历史奇闻”)。我认为正确的方法是获取当前堆栈指针 stack base (pthread_attr_getstackaddr),并检查您的指针是否介于两者之间。
猜你喜欢
  • 1970-01-01
  • 2012-07-29
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
  • 2021-05-18
  • 2012-11-23
  • 1970-01-01
相关资源
最近更新 更多