gpt4 book ai didi

rust - "Rust Essentials"这本书关于变量在堆栈或堆中的位置是否正确?

转载 作者:行者123 更新时间:2023-11-29 07:45:23 29 4
gpt4 key购买 nike

我在 Ivo Balbaert 所著的 Rust Essentials 一书中找到了获取变量内存位置的代码,在第 2 章中关于“堆栈和堆”的内容:

let a = 32;
let mut b = "str";
println!({:p} {:p}, &a, &b);

书上有输出 0x23fba4 0x23fb90,它指出第一个地址是堆栈中的位置,第二个是堆中的位置。

我对这个说法有些怀疑,因为我听说栈地址是朝着内存地址递减的方向增长的。上面的第二个地址似乎是堆栈中的一个位置。

我错了吗?

引用:

Now, we will run the following program and try to visualize the program's memory: // see Chapter 2/code/references.rs

let health = 32;
let mut game = "Space Invaders";

Values are stored in memory and so they have memory addresses. The health variable contains an integer value 32 that is stored in the stack at location 0x23fba4, while the variable game contains a string, which is stored in the heap starting at location 0x23fb90. (These were the addresses when I executed the program, but they will be different when you run the program.)

The variables to which the values are bound are pointers or references to the values. They point to them; game is a reference to Space Invaders. The address of a value is given by the & operator. So, &health is the address where value 32 is stored, and &game is the address where the Space Invaders' value is stored. We can print these addresses by using the format string {:p} for pointers like this:

println!("address of health-value: {:p}", &health); // prints 0x23fba4
println!("address of game-value: {:p}", &game); // prints 0x23fb90

最佳答案

作为user4815162342 commented ,书错了。作为变量 b 的胖指针位于堆栈中,就像 a 一样。只有它指向的字符串数据可以在其他地方。

在示例 let mut b = "str"; 中,字符串数据实际上离堆很远。它静态放置在 data segment 中。你的程序。要真正将它放在堆上,我们需要使用 let b = String::from("str");。生成的内存如下图所示:

enter image description here

让我们手动检查内存以查看发生了什么。

假设 ab 位于地址 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);

输出看起来像这样:

[32, 0, 0, 0, 128, 85, 251, 177, 191, 85, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]

  • 32, 0, 0, 0:a的四个字节
  • 128, 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

虽然 ab 位于相同的内存区域 (0x7f...),但字符串数据位于不同的区域 (0x7e...)。

// print content of pointer
let s: &[u8] = unsafe {
slice::from_raw_parts(p, 4)
};
println!("{:?}", s); // [115, 116, 114, 32]

前三个字节包含 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);
}

请注意,该代码示例采用 64 位指针并依赖于编译器的实现细节,并且可能在将来或在其他系统上中断。特别是,无法保证堆栈框架或 &str 的布局。请不要在实际代码中使用任何这些:)

关于rust - "Rust Essentials"这本书关于变量在堆栈或堆中的位置是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50596507/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com