Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are string literals immutable?

I am reading the Rust book to learn Rust and currently learning about ownership. It mentions that:

We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t suitable for every situation in which we may want to use text. One reason is that they’re immutable.

The code below runs without any problem. Here I changed the value of a, if immutable strings can be changed what’s the problem stated there?

fn main() {
   let mut a = "Hello";
   println!("{}", a);
   a = " World";
   println!("{}", a);
}
like image 434
IcanCode Avatar asked Sep 04 '26 17:09

IcanCode


1 Answers

The executable binary produced by the rust compiler contains the string literals "Hello" and "World" in the read-only data section rodata.

$ cargo build --release
$ readelf -x .rodata target/release/demo | grep Hello
  0x0003c000 48656c6c 6f000000 0a576f72 6c640000 Hello....World..

Because these literals are placed in an immutable section, the operating system prohibits modifying them.

fn main() {
    let mut a: &'static str = "Hello";
    println!("{}", a);

    unsafe { (a.as_ptr() as *mut char).write('x') };
    println!("{}", a);
}
$ cargo run
Hello
Segmentation fault

However, the variable a is of type &str, so a pointer to a string slice, and it lives on the stack. Therefore, it is totally valid in your example for a to first point to the address of "Hello", and then to the address of "World".


Information about the unsafe block:

We want to write something to the address where a points to, to show that it is indeed stored in a read-only section.

a is declared as mut a: &str, meaning the variable is mutable, but the data (string literal) is immutable (in contrast to mut a: &mut str 😉️). Thus, the compiler prevents us from using a.as_mut_ptr() to get a mutable (aka writable) pointer to the underlying bytes.

Instead, we have to do a little trick: Use a.as_ptr() and cast the returned *const u8 to a *mut char. Finally, writing to a pointer requires an unsafe block, because you can violate Rust's memory safety with it, which can result in bad things happening, like the Segmentation Fault shown above.

like image 185
linuskmr Avatar answered Sep 08 '26 02:09

linuskmr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!