메모리에서의 참조
&String이나 &mut String 같은 참조는 메모리에서 어떻게 표현될까요?
Rust에서 대부분의 참조1는 가리키는 대상의 메모리 주소를 담은 **포인터(Pointer)**로 표현됩니다. 따라서 참조의 크기는 시스템의 포인터 크기인 usize와 같습니다.
std::mem::size_of를 통해 이를 직접 확인할 수 있습니다.
assert_eq!(std::mem::size_of::<&String>(), 8); // 64비트 시스템 기준 assert_eq!(std::mem::size_of::<&mut String>(), 8);
특히 &String은 String의 메타데이터(포인터, 길이, 용량)가 저장된 스택 위치를 가리키는 포인터입니다. 예를 들어 다음 코드를 실행해 볼까요?
let s = String::from("Hey");
let r = &s;
이때 메모리 구조는 다음과 같아집니다.
--------------------------------------
| |
+----v----+--------+----------+ +----|----+
스택 | 포인터 | 길이 | 용량 | | 포인터 |
| | | 3 | 5 | | |
+--| ----+--------+----------+ +---------+
| s r
|
v
+---+---+---+---+---+
힙 | H | e | y | ? | ? |
+---+---+---+---+---+
그림에서 보듯 r은 힙을 직접 가리키는 것이 아니라, 힙을 관리하는 스택의 s를 가리킵니다. 즉, ’힙 데이터를 가리키는 포인터’를 가리키는 포인터인 셈이죠. &mut String 역시 이와 동일한 방식으로 작동합니다.
모든 포인터가 힙을 가리키지는 않습니다
여기서 중요한 점 한 가지는, 모든 포인터가 반드시 힙을 가리키는 것은 아니라는 사실입니다. 포인터는 그저 메모리의 특정 위치를 가리킬 뿐이며, 그 위치는 힙일 수도 있고 스택일 수도 있습니다.
Exercise
The exercise for this section is located in 03_ticket_v1/10_references_in_memory