인덱스 범위를 벗어난 접근
인덱스 범위를 벗어난 접근 (Index out of Bounds)
배열이나 슬라이스에 array[5]처럼 인덱스를 벗어나게 접근하면 컴파일러가 가만히 두지 않아요. 그 접근이 컴파일 타임에도 일어나는지, 아니면 실행 중에 일어나는지에 따라 처리 방식이 조금 달라지는데, 두 경우를 나란히 확인해 볼게요.
본문
컴파일 타임
컴파일러가 값의 길이를 알 수 있는 상황(컴파일 타임)에서는, 범위를 벗어난 인덱스를 컴파일 에러로 잡아 줍니다.
comptime {
const array: [5]u8 = "hello".*;
const garbage = array[5];
_ = garbage;
}
$ zig test test_comptime_index_out_of_bounds.zig
/home/ci/work/zig-bootstrap/zig/doc/langref/test_comptime_index_out_of_bounds.zig:3:27: error: index 5 outside array of length 5
const garbage = array[5];
^
길이 5짜리 배열에 인덱스 5로 접근하려다 index 5 outside array of length 5라는 컴파일 에러를 받았어요. 컴파일러가 array[5]가 배열 밖을 가리킨다는 걸 미리 알아챈 거죠.
런타임
길이가 실행 중에만 알려지는 상황(예: 함수로 슬라이스를 받았을 때)에서는 컴파일 타임에 잡을 수 없어요. 이 경우에는 **실행 도중 안전성 검사(runtime safety check)**가 발동해서, 범위를 벗어나면 패닉(panic)을 일으킵니다.
pub fn main() void {
const x = foo("hello");
_ = x;
}
fn foo(x: []const u8) u8 {
return x[5];
}
$ zig build-exe runtime_index_out_of_bounds.zig
$ ./runtime_index_out_of_bounds
thread 972133 panic: index out of bounds: index 5, len 5
/home/ci/work/zig-bootstrap/zig/doc/langref/runtime_index_out_of_bounds.zig:7:13: 0x11e836e in foo (runtime_index_out_of_bounds.zig)
return x[5];
^
/home/ci/work/zig-bootstrap/zig/doc/langref/runtime_index_out_of_bounds.zig:2:18: 0x11e829a in main (runtime_index_out_of_bounds.zig)
const x = foo("hello");
^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:788:64: 0x11e7bbb in callMain (std.zig)
if (fn_info.param_types.len == 0) return wrapMain(root.main());
^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:248:5: 0x11e75e1 in _start (std.zig)
asm volatile (switch (native_arch) {
^
(process terminated by signal)
여기서 foo가 받은 x는 슬라이스라 길이가 컴파일 타임에 확정되지 않았어요. 그래서 x[5]에 도달하는 순간 panic: index out of bounds: index 5, len 5라는 메시지와 함께 프로세스가 종료됐죠. index 5가 접근하려던 인덱스, len 5가 실제 길이예요.
더 알아보기 (Learn more)
인덱스로 접근하는 대상의 기본 개념을 복습하고 싶다면 여기를 살펴보세요.