Where are the bytes?

Where are the bytes?

Zig에서 값이 실제로 메모리의 어디에 놓이는지는 변수의 종류에 따라 정해져요. 문자열 리터럴(String literal)부터 살펴보면, 바이트들이 컴파일 이후 어디에 저장되는지 한눈에 이해할 수 있어요.

출처: Zig Documentation

본문

"hello" 같은 문자열 리터럴(String literal)은 **전역 상수 데이터 섹션(global constant data section)**에 놓여요. 그래서 문자열 리터럴을 가변 슬라이스(mutable slice)에 넘기면 에러가 나요. 이런 코드를 보면 잘 드러나요:

fn foo(s: []u8) void {
    _ = s;
}

test "string literal to mutable slice" {
    foo("hello");
}

이를 컴파일하면 다음과 같은 에러가 나요.

$ zig test test_string_literal_to_slice.zig
/home/ci/work/zig-bootstrap/zig/doc/langref/test_string_literal_to_slice.zig:6:9: error: expected type '[]u8', found '*const [5:0]u8'
    foo("hello");
        ^~~~~~~
/home/ci/work/zig-bootstrap/zig/doc/langref/test_string_literal_to_slice.zig:6:9: note: cast discards const qualifier
/home/ci/work/zig-bootstrap/zig/doc/langref/test_string_literal_to_slice.zig:1:11: note: parameter type declared here
fn foo(s: []u8) void {
          ^~~~

그런데 슬라이스를 상수(constant)로 만들면 정상 동작해요:

fn foo(s: []const u8) void {
    _ = s;
}

test "string literal to constant slice" {
    foo("hello");
}
$ zig test test_string_literal_to_const_slice.zig
1/1 test_string_literal_to_const_slice.test.string literal to constant slice...OK
All 1 tests passed.

문자열 리터럴과 마찬가지로, 값이 comptime에 알려진 const 선언들도 전역 상수 데이터 섹션에 저장돼요. Compile Time Variables도 마찬가지로 전역 상수 데이터 섹션에 놓여요.

함수 안에 선언된 var 변수들은 함수의 **스택 프레임(stack frame)**에 저장돼요. 함수가 반환되면 그 함수의 스택 프레임에 있는 변수를 가리키는 Pointers는 모두 유효하지 않은 참조가 되고, 이를 역참조(dereference)하면 검사되지 않는 Illegal Behavior가 돼요.

최상위(top level)에서 선언된 var 변수나 struct 선언 안의 var 변수들은 **전역 데이터 섹션(global data section)**에 저장돼요.

allocator.alloc 또는 allocator.create로 할당한 메모리의 위치는 할당자(allocator)의 구현이 결정해요.

참고: thread local variables 관련 내용은 아직 문서에 TODO로 남아 있어요.

더 알아보기