简体   繁体   English

“String”总是分配在堆上吗?

[英]Is "String" always allocated on the heap?

In this Rust documentation , it is written that:在这份Rust 文档中,写道:

String is allocated on the heap.字符串分配在堆上。

However, when I look at the memory mapping, I see that it is allocated in the stack...但是,当我查看 memory 映射时,我发现它是在堆栈中分配的...

Let's consider the basic Rust source file below:让我们考虑下面的基本 Rust 源文件:

// rustc -o string_vs_str -C opt-level=0 -C debuginfo=2 main.rs

fn main() {
    let my_string: String = String::from("abc");
    let my_str: &str = "def";
    println!("{}{}", my_string, my_str);
    let my_string_str: &str = my_string.as_str();
    println!("my_string_str: {}", my_string_str);
}

Let's executed RUST-GDB on the executable, upon the following commands:让我们根据以下命令在可执行文件上执行 RUST-GDB:

# rust-gdb --batch --command=test.gdb --args ./string_vs_str

set width 0
set height 0
set verbose off

### Set 2 breakpoints
b main.rs:6
b main.rs:8

### Start the process
r

### Display the memory mapping into the file "map.txt"
set logging redirect on
set logging file map.txt
set logging overwrite on
set logging enabled on
info proc map
set logging enabled off

### Get information about "my_string"
echo == my_string ==\n
print my_string
ptype my_string
print &my_string
print my_string.vec
c

### Get information about "my_str"
echo == my_str ==\n
print my_str
ptype my_str
print &my_str
print my_str.length
print my_str.data_ptr

The result is given below:结果如下:

Breakpoint 1, main::main () at main.rs:6
6       println!("{}{}", my_string, my_str);
== my_string ==
$1 = "abc"
type = struct alloc::string::String {
  vec: alloc::vec::Vec<u8, alloc::alloc::Global>,
}
$2 = (*mut alloc::string::String) 0x7fffffffd960
$3 = Vec(size=3) = {97, 98, 99}
abcdef

Breakpoint 2, main::main () at main.rs:8
8       println!("my_string_str: {}", my_string_str);
== my_str ==
$4 = "def"
type = struct &str {
  data_ptr: *mut u8,
  length: usize,
}
$5 = (*mut &str) 0x7fffffffd978
$6 = 3
$7 = (*mut u8) 0x55555559304f

And the content of the (logged) file " map.txt " is:而(记录的)文件“ map.txt ”的内容是:

process 11932
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
      ...
      0x5555555a5000     0x5555555c6000    0x21000        0x0  rw-p   [heap]
      0x7ffff7d5c000     0x7ffff7d5f000     0x3000        0x0  rw-p   
      ...
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0  rw-p   [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0  --xp   [vsyscall]

Please note: I have removed some lines that I consider as not important.请注意:我删除了一些我认为不重要的行。

Unless I am mistaken:除非我记错了:

  • the head starts at 0x5555555a5000 and ends at 0x5555555c6000 .头部从0x5555555c6000开始,到0x5555555a5000结束。
  • the stack starts at 0x7ffffffde000 and ends at 0x7ffffffff000 .堆栈从0x7ffffffff000开始,到0x7ffffffde000结束。
  • the variable my_string is allocated at 0x7fffffffd960 .变量my_string分配在0x7fffffffd960处。
  • the variable my_str is allocated at 0x7fffffffd978 .变量my_str分配在0x7fffffffd978处。

OK.好的。 Thus, unless I am mistaken, both my_string and my_str are allocated in the stack:因此,除非我弄错了,否则my_stringmy_str都分配在堆栈中:

VAR my_string VAR my_string

my_string at 0x7fffffffd960 : my_string位于0x7fffffffd960处:

$ value="7fffffffd960"  # address of my_string
$ start="7ffffffde000"  # start of the stack
$ stop="7ffffffff000"   # end of the stack
$ echo "obase=16;ibase=16;${value^^} > ${start^^}" | bc
1
$ echo "obase=16;ibase=16;${value^^} < ${stop^^}" | bc
1

Thus: 0x7ffffffde000 < &my_string < 0x7ffffffff000 => my_string is allocated in the stack.因此: 0x7ffffffde000 < &my_string < 0x7ffffffff000 => my_string在堆栈中分配。

VAR my_str VAR my_str

my_str.data_ptr at 0x7fffffffd978 : 0x7fffffffd978处的my_str.data_ptr

$ value="7fffffffd978"  # address of my_str.data_ptr
$ start="7ffffffde000"  # start of the stack
$ stop="7ffffffff000"   # end of the stack
$ echo "obase=16;ibase=16;${value^^} > ${start^^}" | bc
1
$ echo "obase=16;ibase=16;${value^^} < ${stop^^}" | bc
1

Thus: 0x7ffffffde000 < &my_str.data_ptr < 0x7ffffffff000 => my_str.data_ptr is allocated in the stack.因此: 0x7ffffffde000 < &my_str.data_ptr < 0x7ffffffff000 => my_str.data_ptr被分配到栈中。

my_str.length at 0x55555559304f : my_str.length0x55555559304f处:

$ value="55555559304f"  # adress of my_str.length
$ start="5555555a5000"  # start of the heap
$ stop="5555555c6000"   # end of the heap
$ echo "obase=16;ibase=16;${value^^} > ${start^^}" | bc
0
$ echo "obase=16;ibase=16;${value^^} < ${stop^^}" | bc
1

Thus: &my_str.length is not allocated in the stack nor it is in the heap.因此: &my_str.length既不在栈中也不在堆中分配。

Conclusion:结论:

The structure that defines " str " is allocated in the stack.定义“ str ”的结构分配在堆栈中。

The vector that defines the content of a "String" is also allocated in the stack.定义“字符串”内容的向量也在堆栈中分配。

What's wrong with this experiment?这个实验有什么问题?

The String and &str variables themselves are allocated on the stack (the length, data pointer and capacity for String ). String&str变量本身在堆栈上分配( String的长度、数据指针和容量)。 But the data they point at is allocated on the heap for String , and at .rodata for your &str .但是它们指向的数据分配在String的堆上,以及&str.rodata上。

To see that, print my_string.vec.buf.ptr.pointer.pointer (yep, that's long) and my_str.data_ptr .要看到这一点,请打印my_string.vec.buf.ptr.pointer.pointer (是的,那很长)和my_str.data_ptr You will see that the first points at the heap and the second is mapped to the executable.您将看到第一个指向堆,第二个指向可执行文件。 These are the data pointers.这些是数据指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM