7

Section 4.3 about slices of The Rust Programming Language has this paragraph:

String Literals Are Slices

Recall that we talked about string literals being stored inside the binary. Now that we know about slices, we can properly understand string literals:

let s = "Hello, world!";

The type of s here is &str: it’s a slice pointing to that specific point of the binary. This is also why string literals are immutable; &str is an immutable reference.

Now, a string slice is, as they've covered earlier, a pair (of some sort) containing a pointer and a length. To me, this paragraph (specifically "we talked about string literals being stored inside the binary" and "pointing to that specific point of the binary") seems to imply that that pointer goes straight into program memory. Not the stack, not the heap, but the actual place where the processor stores all the instructions that the program consists of. A specific line of the assembly, if you will.

Is this true? If not, what else could they mean by that, and how is it actually done? How can I figure this out myself if I have a similar question later along the line?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Arthur
  • 653
  • 2
  • 6
  • 21
  • 1
    String *literals* are static constants. They don't need to copied to the heap or stack, you can reference them directly in program memory. Notice you can also get string slices from [dynamically allocated strings](https://doc.rust-lang.org/beta/std/string/struct.String.html) – Bergi Aug 13 '18 at 14:57
  • If you try to examine such program in Godbolt's compiler explorer, you will see the assembly pseudo-instruction ('directive'?) that "bakes" the string into the binary (around line 169 when I compiled it) https://godbolt.org/g/GBsmCt – justinas Aug 13 '18 at 14:58
  • @justinas I'm pretty certain the example could be made shorter if you didn't have to _print_ the thing, but that is a cool tool. Do I have to learn (at least a little bit of) assembly now too? – Arthur Aug 13 '18 at 14:59
  • 1
    "*Not the stack, not the heap, but the actual place where the processor stores all the instructions that the program consists of.*" - yes, that's what they mean by "the binary". "*A specific line of the assembly, if you will*", yeah, although this part is not executable code, it's plain data not instructions. – Bergi Aug 13 '18 at 15:00
  • @Arthur I was worried that the compiler would optimize it out if it was unused, but it seems that "-C opt-level=0" helps avoid that. – justinas Aug 13 '18 at 15:01

2 Answers2

9

It's true - &'static str string literals are embedded within the binary itself. This is not unique to Rust, e.g. C implementations often do the same thing.

Citing the Rust Reference (emphasis mine):

A string literal is a string stored directly in the final binary, and so will be valid for the 'static duration.

Its type is 'static duration borrowed string slice, &'static str.

There are programs designed specifically to find these kinds of strings, e.g. strings or just grep --text.

Related question:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ljedrz
  • 20,316
  • 4
  • 69
  • 97
  • *`&'static str` string literals are embedded within the binary itself* — note the answer is correct but is being very specific: only for **literals**. You [can create a `&'static str`](https://stackoverflow.com/a/30527289/155423) that is not from a literal and thus would not be part of the binary's data. – Shepmaster May 03 '21 at 19:51
-1

&str is not a single structure but two, sequence of bytes that encodes the actual text that is stored in read only data section (It is .rodata for LEF but could be different depending on executable format) of the binary and a slice that has the information where this sequence starts and its length in bytes.

A slice is a two-word object, the first word is a pointer to the data and the second word is the length of it.

Rather than checking for null byte to determine where the string ends, Rust keep tracks the number of bytes this text takes up to know where it ends.

snnsnn
  • 10,486
  • 4
  • 39
  • 44