我正在阅读 Rust 书来学习 Rust,目前正在学习所有权。它提到:
我们已经看到了字符串文字,其中字符串值是硬编码的 进入我们的程序。字符串字面量很方便,但实际上并非如此 适用于我们可能想要使用文本的每种情况。一 原因是它们是不可变的。
下面的代码运行没有任何问题。在这里我改变了
a
的值,如果不可变字符串可以改变那里说明的问题是什么?
fn main() {
let mut a = "Hello";
println!("{}", a);
a = " World";
println!("{}", a);
}
rust 编译器生成的可执行二进制文件在只读数据部分包含字符串文字“Hello”和“World”
rodata
.
$ cargo build --release
$ readelf -x .rodata target/release/demo | grep Hello
0x0003c000 48656c6c 6f000000 0a576f72 6c640000 Hello....World..
因为这些字面量被放在一个不可变的部分,所以操作系统禁止修改它们。
fn main() {
let mut a: &'static str = "Hello";
println!("{}", a);
unsafe { (a.as_ptr() as *mut u8).write(42) };
println!("{}", a);
}
$ cargo run
Hello
Segmentation fault
但是,variable
a
是 &str
类型,所以是一个指向字符串切片的指针,它存在于堆栈中。因此,a
先指向“Hello”的地址,再指向“World”的地址是完全有效的。
编辑:关于
unsafe
块的信息
我们想在
a
指向的地址写入一些东西,以表明它确实存储在只读部分。
a
被声明为 mut a: &str
,这意味着变量是可变的,但数据(字符串文字)是不可变的(与 mut a: &mut str
😉️相反)。
因此,编译器阻止我们使用 a.as_mut_ptr()
来获取指向底层字节的可变(又名可写)指针。
a.as_ptr()
并将返回的const *u8
转换为mut *u8
。最后,写入指针需要一个 unsafe
块,因为你可能会违反 Rust 的内存安全,这可能会导致不好的事情发生,如上面所示的分段错误。