英文:
How are Rust references stores in Memory (Specifically Stack)
问题
I have been learning about references in Rust and finding it hard to understand as on how exactly are references been stored in stack.
Consider the below program:
fn main() {
let name = String::from("Somu");
let name_ref = &name;
}
Now, How does memory is allocated in the stack frame for these 2 variables?
|--------------------|
| name | 0x1fcd |
|--------------------|
| name_ref | ? |
|--------------------|
So, since String are stored in heap, we have the address of heap where the string "Somu" is present as the value for the variable name
.
Now, name_ref
is a reference to name
. In Rust terms, name_ref
borrows the value pointed by name
.
So what gets stored in the stack frame as the value for name_ref
?
- Address to the heap memory containing the string?
- Address of
name
in stack?
Or something else?
Can someone please enrich me with the concept?
Thanks in advance
英文:
I have been learning about references in Rust and finding it hard to understand as on how exactly are references been stored in stack.
Consider the below program:
fn main() {
let name = String::from("Somu");
let name_ref = &name;
}
Now, How does memory is allocated in the stack frame for these 2 variables?
|--------------------|
| name | 0x1fcd |
|--------------------|
| name_ref | ? |
|--------------------|
So, since String are stored in heap, we have the address of heap where the string "Somu" is present as the value for the variable name
.
Now, name_ref
is a reference to name
. In Rust terms, name_ref
borrows the value pointed by name
.
So what get's stored in the stack frame as the value for name_ref
?
- Address to the heap memory containing the string?
- Address of
name
in stack?
Or something else?
Can someone please enrich me with the concept?
Thanks in advance
答案1
得分: 5
以下是翻译好的部分:
那么作为name_ref的值存储在堆栈帧中的是什么?
在堆栈中存储了name
的地址。
引用是指针,具有编译器在编译期间了解的一些附加属性(可变性、别名、保证指向现有对象、借用的生命周期等)。但最终它们在底层只是普通的指针。它们的大小为usize
(除了宽/胖指针之外)。并保存它们所指向的东西的内存地址。
您可以通过使用{:p}
格式化来打印指针的地址来验证:
fn main() {
let name = String::from("Somu");
let name_ref = &name;
println!("{:p}", &name as *const _);
println!("{:p}", name_ref);
println!("{:p}", name.as_bytes() as *const _);
}
例如,这可以输出:
0x7ffff3dd1350
0x7ffff3dd1350
0x55dfd62769d0
前两个地址是堆栈变量name
的地址,第三个地址是String
管理的堆分配的地址。
英文:
> So what get's stored in the stack frame as the value for name_ref?
Address of name
in stack.
References are pointers with some additional properties that compiler knows about during compilation (mutabiliy, aliasing, guarantee of pointing to existing object, lifetime of the borrow, etc.). But in the end they are just a plain old pointer under the hood. They have size of usize
(except wide/fat pointers). And hold a memory address of the thing they point to.
You can verify that by printing address of a pointer using {:p}
formatting:
fn main() {
let name = String::from("Somu");
let name_ref = &name;
println!("{:p}", &name as *const _);
println!("{:p}", name_ref);
println!("{:p}", name.as_bytes() as *const _);
}
This could for example output:
0x7ffff3dd1350
0x7ffff3dd1350
0x55dfd62769d0
Where two first addresses are addresses of stack variable name
and third address is an address of a heap allocation that String
manages.
答案2
得分: 2
A String
可以被视为一个具有三个数据成员的结构体。
- 一个指向存储 UTF-8 字节的堆分配存储空间的指针,用于构成文本,
- 一个用于存储空间容量的整数,
- 一个用于实际在该存储空间中使用的字节数的整数(<=容量,用于高效的调整大小策略)。
当我们说一个 String
是堆分配的时候,这只是一种强调文本(UTF-8 字节序列)是堆分配的快捷方式;结构体本身可能是堆栈分配的(取决于你的代码)。
在你的示例中,name
String
(结构体)是堆栈分配的,就像任何局部变量一样,尽管它包含的文本可能是堆分配的,并且 name_ref
只是包含了该结构体在堆栈上的地址(然后它指向堆栈上非常近的地址)。
请注意,这种描述代码功能的方式是非优化编译器(如调试模式中的编译器)可能会采用的一种简化视图,其中每个变量都位于内存中并具有一个地址。
当涉及到优化编译器(如发布模式中的编译器)时,许多变量不仅仅存在于内存中(具有专用存储空间),它们会被重构为一系列在寄存器上进行等效操作和非常少的内存访问。
英文:
A String
can be seen as a struct with three data members.
- a pointer to a heap-allocated storage for the utf-8 bytes constituting the text,
- an integer for the capacity of this storage,
- an integer for the amount of bytes actually used in this storage (<=capacity, for efficient resizing strategies).
When we say that a String
is heap-allocated, it's simply a shortcut to emphasize the fact that the text (sequence of utf-8 bytes) is heap-allocated; the struct itself is probably stack-allocated (depending upon your code).
In your example, the name
String
(the struct) is stack-allocated, as any local variable, although the text it contains is probably heap allocated, and the name_ref
simply contains the address of this struct on the stack (it points to a very near address on the stack then).
Note that this way of describing what the code does is a simplistic view of what could do a non-optimizing compiler (as in debug mode), where each variable is located in memory and has an address.
When it comes to an optimizing compiler (as in release mode), many variables don't simply exist has is (with a dedicated storage in memory), they are refactored into a series of equivalent operations on registers and very few memory accesses.
答案3
得分: 0
这是对堆栈上存储的String
值的引用,这意味着引用将存储指向该值的指针。引用不会指向堆;该分配是String
内部的。
然而,在编译器优化存在的情况下,这种引用很可能会被省略。
值得注意的是,解引用强制允许从&String
创建一个&str
绑定,在这种情况下,对于非空的String
,&str
将指向堆。
英文:
It's a reference to the String
value stored on the stack, which means that the reference would store a pointer to that value. The reference would not refer to the heap; that allocation is internal to the String
.
However, in the presence of compiler optimizations, it's very likely that this kind of reference will be elided.
It's also worth noting that deref coercion allows creating a &str
binding from a &String
, and a &str
in that case would point to the heap for a non-empty String
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论