2015-05-10 66 views
4

我不知道是否有辦法找出一個變量是堆棧還是堆分配。如何判斷是否有堆或堆棧分配?

考慮一下:

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()

+2

想到的第一個問題是*「爲什麼?」*。什麼樣的代碼會與這些知識有所不同? – Shepmaster

+1

我不需要這個代碼來發現任何不同於發現語言的東西:) – Christoph

+4

0x1是Rust分配器爲零大小對象返回的虛擬地址,它不在堆上。參見[heap.rs#L90](https://github.com/rust-lang/rust/blob/9ecc9896dedb426e3f4eb3d23dfc60192fe5275f/src/liballoc/heap.rs#L90)。 – thelink2012

回答

4

如果你是一些POSIX系統上,你也許可以使用sbrk()系統調用的0參數來確定程序中斷的當前位置,這是的限流堆。如果給定值的地址小於這個地址但大於堆的開始,那麼它就在堆上。我不知道如何檢查它是否在堆棧上,但不一定會自動選擇不堆在堆上,因爲它也可以是靜態初始化或未初始化的數據,儘管這可能是顯而易見的你檢查了代碼。您可以在x86_64架構上使用rbp寄存器,該架構應該指向當前堆棧幀的開始。這就是如果你想檢查它是否在當前的堆棧幀上,或者如果你想檢查它是否在堆棧上的任何地方,你可以使用rsp

我想你可以通過使用end參數得到end()系統調用堆的開始。所以堆的下界將是end(end)的結果,上界將是sbrk(0)