字符串 str
字符串切片 &str
字符串切片的内存布局
首先看一个小例子:
use std::mem::size_of_val; #[allow(unused_variables)] #[allow(clippy::size_of_ref)] fn main() { let s: &str = "Rust"; let s2 = s; assert_eq!(s, s2); // 字符串切片的长度为4, 因为字符串字面量的值有 4 个字节 assert_eq!(size_of_val(s), 4); // 字符串切片本身是一个切片类型, 其占用的内存是 16 个字节, | ptr: usize | len: usize | assert_eq!(size_of_val(&s), 16); }
可以看下生成的汇编代码:
.section .text._ZN17string_mem_layout4main17hb4d59e5a01423cd2E,"ax",@progbits
.p2align 4, 0x90
.type _ZN17string_mem_layout4main17hb4d59e5a01423cd2E,@function
_ZN17string_mem_layout4main17hb4d59e5a01423cd2E:
.cfi_startproc
subq $120, %rsp
.cfi_def_cfa_offset 128
leaq .L__unnamed_3(%rip), %rax
movq %rax, 16(%rsp)
movq $4, 24(%rsp)
movq 16(%rsp), %rcx
movq 24(%rsp), %rax
movq %rcx, 32(%rsp)
movq %rax, 40(%rsp)
leaq 16(%rsp), %rax
movq %rax, 48(%rsp)
leaq 32(%rsp), %rax
movq %rax, 56(%rsp)
movq 48(%rsp), %rdi
movq %rdi, (%rsp)
movq 56(%rsp), %rsi
movq %rsi, 8(%rsp)
callq _ZN4core3cmp5impls69_$LT$impl$u20$core..cmp..PartialEq$LT$$RF$B$GT$$u20$for$u20$$RF$A$GT$2eq17h01b3e2146858edabE
testb $1, %al
jne .LBB15_2
movq 8(%rsp), %rdx
movq (%rsp), %rsi
movb $0, 71(%rsp)
movq $0, 72(%rsp)
movzbl 71(%rsp), %edi
leaq .L__unnamed_4(%rip), %r8
leaq 72(%rsp), %rcx
callq _ZN4core9panicking13assert_failed17h78d8de08a404e5a1E
.LBB15_2:
addq $120, %rsp
.cfi_def_cfa_offset 8
retq
.Lfunc_end15:
.size _ZN17string_mem_layout4main17hb4d59e5a01423cd2E, .Lfunc_end15-_ZN17string_mem_layout4main17hb4d59e5a01423cd2E
.cfi_endproc
.type .L__unnamed_3,@object
.section .rodata.cst4,"aM",@progbits,4
.L__unnamed_3:
.ascii "Rust"
.size .L__unnamed_3, 4
上面的代码中, 先定义了一个字符串字面量, 并用它来初始化字符串切片 s
,
字符串切片 s
的内存包含了两个部分:
- 指向字符串字面量内存的指针
- 以及字符串字面量的长度, 为4个字节
字符串字面量的值位于 rodata
segment, 被嵌在了程序的二进制文件中, 在整个进程的运行期间它都是有效的.