ean*_*ner 8 heap-memory stack-memory rust
我发现代码来获取存储位置在本书变量锈要点中关于"栈和堆"第2章伊沃Balbaert:
let a = 32;
let mut b = "str";
println!({:p} {:p}, &a, &b);
Run Code Online (Sandbox Code Playgroud)
这本书有输出0x23fba4 0x23fb90,它说明第一个地址是堆栈中的位置,第二个地址是堆中的位置.
我对这个陈述有一些疑问,因为我听说堆栈地址越来越朝向减少内存地址.上面的第二个地址似乎是堆栈中的一个位置.
我错了吗?
引用:
现在,我们将运行以下程序并尝试可视化程序的内存://参见第2章/ code/references.rs
Run Code Online (Sandbox Code Playgroud)let health = 32; let mut game = "Space Invaders";值存储在内存中,因此它们具有内存地址.运行状况变量包含一个整数值32,它存储在位于0x23fba4的堆栈中,而变量游戏包含一个字符串,该字符串存储在从位置0x23fb90开始的堆中.(这些是我执行程序时的地址,但是在运行程序时它们会有所不同.)
绑定值的变量是指针或对值的引用.他们指向他们; 游戏是对太空入侵者的参考.值的地址由&运算符给出.因此,&health是存储值32的地址,&game是存储Space Invaders值的地址.我们可以使用格式字符串{:p}打印这些地址,如下所示:
Run Code Online (Sandbox Code Playgroud)println!("address of health-value: {:p}", &health); // prints 0x23fba4 println!("address of game-value: {:p}", &game); // prints 0x23fb90
kaz*_*ase 10
正如用户4815162342评论的那样,这本书是错误的.作为变量的胖指针b就像是一样a.只有它指向的字符串数据才能在其他地方.
在示例中let mut b = "str";,字符串数据实际上不在堆附近.它静态地放在程序的数据段中.要真正将它放在我们需要使用的堆上let b = String::from("str");.生成的内存将如下图所示:
让我们手动检查内存,看看发生了什么.
说a并且b位于地址0x7ffeda6df61c和0x7ffeda6df620.
// print part of stack memory starting at &a
let m: &[u8] = unsafe {
slice::from_raw_parts(&a as *const _ as *const u8, 4 + 16)
};
println!("{:?}", m);
Run Code Online (Sandbox Code Playgroud)
输出看起来像这样:
[32, 0, 0, 0, 128, 85, 251, 177, 191, 85, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]
32, 0, 0, 0:四个字节 a128, 85, 251, 177, 191, 85, 0, 0:第一部分b,64位指向字符串数据的指针3, 0, 0, 0, 0, 0, 0, 0:第二部分b,字符串的长度现在按照数据指针:
// manually follow the data pointer
let address = unsafe {
*(&b as *const _ as *const usize)
};
let p = address as *const u8;
println!("{:p}", p); // 0x55bfb1fb5580
Run Code Online (Sandbox Code Playgroud)
而a与b驻留在同一存储区域(0x7F的...),该字符串数据是在不同的区域(0x7e格式...).
// print content of pointer
let s: &[u8] = unsafe {
slice::from_raw_parts(p, 4)
};
println!("{:?}", s); // [115, 116, 114, 32]
Run Code Online (Sandbox Code Playgroud)
前三个字节包含s,t和r的ASCII代码.第四个字节是任意垃圾.
以下是完整的代码.
use std::slice;
fn main() {
let a: i32 = 32;
let b = String::from("str");
println!("{:p} {:p}", &a, &b);
// print part of stack memory starting at a
let m: &[u8] = unsafe {
slice::from_raw_parts(&a as *const _ as *const u8, 4 + 16)
};
println!("{:?}", m);
// manually follow the str pointer
let address = unsafe {
*(&b as *const _ as *const usize)
};
let p = address as *const u8;
println!("{:p}", p);
// print content of pointer
let s: &[u8] = unsafe {
slice::from_raw_parts(p, 4)
};
println!("{:?}", s);
}
Run Code Online (Sandbox Code Playgroud)
请注意,代码示例假设64位指针并依赖于编译器的实现细节,并且可能在将来或其他系统上中断.特别是,堆栈框架的布局或&str不保证.请不要在实际代码中使用任何这些:)
| 归档时间: |
|
| 查看次数: |
176 次 |
| 最近记录: |