0

When declaring the String type, I have a question about how memory is allocated in the stack and heap areas.

I think, the memory allocation image would be below.

let s = String::from("hello world");
(A)                                                (B)            
+======================+----- static memory -------+======================+ 
|          ...         |                           | "hello world"(12)    |
|                      |                           |          ...         |
+======================+------ stack memory -------+======================+
| s(24)                |                           | s(24)                |
| data addr            |                           | data addr            |
| length               |                           | length               |
| capacity             |                           | capacity             |
|          ...         |                           |          ...         |
|                      |                           |                      |
|          ...         |                           |                      |
| "hello world"(12)    |                           |          ...         |
+======================+------- heap memory -------+======================+

Which scenario is correct?

I understand that literal strings are stored in static area during compile time. However, the Rust documentation states that the String type is equivalent to Vec. The Vec type stores all its elements on the heap, so I'm confused as to whether scenario A is correct.

1
  • 2
    Neither scenario is correct, because when you create the String you copy the string literal's contents from static memory onto the heap. Commented Aug 22, 2023 at 17:34

1 Answer 1

3

Neither is correct.

First off, "hello world" is only 11 bytes. Rust does not null-terminate strings.

Essentially, "hello world" is a str stored in the binary's static memory, which is copied from static memory into heap memory. The String struct stores a pointer to the heap memory, the length of the string, and the capacity of the allocation.

pseudo-code:

static_memory = {
  contents: str = "hello world"=
  lit: &str = (&contents, 11)
}

def String_from_strref(text: &str) -> String:
  (pointer, length) = text
  heap_pointer = malloc(length)
  capacity = memcpy(heap_pointer, pointer, length)
  
  return (heap_pointer, length, capacity)

let s = String_from_strref(lit)

And after that executes, memory will look like:

=== stack memory ===+=== heap memory ===+===== static memory =====
 s(24)              |                   |          "hello world"
   pointer ----------> "hello world..." |          ^
   length = 11      |                   | lit(16)  |
   capacity >= 11   |                   |   pointer
                    |                   |   length = 11

Note: order of fields is for educational purposes only and not guaranteed by the layout of the various types

Sign up to request clarification or add additional context in comments.

2 Comments

I don't think you meant that, but from your pseudocode and chart it seems like the &str (the pointer) itself is stored in static memory, which is not.
lowers glasses over nose: Actually, son, since "hello world" is only 11 bytes, it is not encoded in static data memory as such, but encoded directly into the instruction stream. Which is a form of static memory. But nevertheless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.