@setRuntimeSafety
@setRuntimeSafety
도입
함수가 실행되는 스코프에서 런타임 안전성 검사를 켤지 끌지를 정해요. ReleaseFast나 ReleaseSmall처럼 빌드 모드에 따라 안전성 검사가 꺼져 있어도, 특정 블록 안에서는 다시 켜고 싶을 때 유용해요.
본문
@setRuntimeSafety(comptime safety_on: bool) void
이 함수가 호출된 스코프에서 런타임 안전성 검사를 켤지(true) 끌지(false)를 설정해요.
직접 예시로 확인해 볼게요.
test "@setRuntimeSafety" {
// The builtin applies to the scope that it is called in. So here, integer overflow
// will not be caught in ReleaseFast and ReleaseSmall modes:
// var x: u8 = 255;
// x += 1; // Unchecked Illegal Behavior in ReleaseFast/ReleaseSmall modes.
{
// However this block has safety enabled, so safety checks happen here,
// even in ReleaseFast and ReleaseSmall modes.
@setRuntimeSafety(true);
var x: u8 = 255;
x += 1;
{
// The value can be overridden at any scope. So here integer overflow
// would not be caught in any build mode.
@setRuntimeSafety(false);
// var x: u8 = 255;
// x += 1; // Unchecked Illegal Behavior in all build modes.
}
}
}
첫 번째 점은 이 빌트인이 호출된 스코프에 적용된다는 거예요. 바깥쪽 테스트 스코프에서는 설정을 건드리지 않았으니, ReleaseFast나 ReleaseSmall 모드에서는 정수 오버플로를 잡아내지 못해요(위의 주석 처리된 x += 1은 바로 그 상황이에요).
하지만 안쪽 블록에서는 @setRuntimeSafety(true)로 다시 켰기 때문에, ReleaseFast나 ReleaseSmall 모드에서조차 이 블록 안에서는 안전성 검사가 동작해요. 그래서 그 아래의 x += 1은 정수 오버플로 검사에 걸려요.
두 번째 점은 어느 스코프에서든 값을 다시 덮어쓸 수 있다는 거예요. 가장 안쪽 블록에서 @setRuntimeSafety(false)로 끄면, 그 바깥 블록에서 켰던 설정과 무관하게 어떤 빌드 모드에서도 오버플로를 잡지 않아요. 이렇게 스코프가 중첩될 때마다 현재 위치의 설정이 우선해요.
-Ofast 모드로 실제 실행하면 어떤 결과가 나오는지 볼까요.
$ zig test test_setRuntimeSafety_builtin.zig -Ofast
1/1 [email protected] 975313 panic: integer overflow
/home/ci/work/zig-bootstrap/out/zig-local-cache/tmp/15625dde49aa511e/../../../../zig/doc/langref/test_setRuntimeSafety_builtin.zig:11:11: 0x107c3c8 in test.@setRuntimeSafety (test)
x += 1;
^
/home/ci/work/zig-bootstrap/out/host/lib/zig/compiler/test_runner.zig:295:25: 0x106eb62 in mainTerminal (test)
if (test_fn.func()) |_| {
^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:789:88: 0x106d066 in callMain (test)
if (fn_info.param_types[0].? == std.process.Init.Minimal) return wrapMain(root.main(.{
^
/home/ci/work/zig-bootstrap/out/host/lib/zig/std/start.zig:248:5: 0x106ccfd in _start (test)
asm volatile (switch (native_arch) {
^
error: the following test command terminated with signal ABRT:
/home/ci/work/zig-bootstrap/out/zig-local-cache/o/1053d260722683c1c582e293d115d193/test --seed=0xf0b4385
빌드 모드가 ReleaseFast(-Ofast)인데도 안쪽 블록에서 안전성 검사를 켰기 때문에, x += 1에서 panic: integer overflow가 발생해요. 이게 바로 @setRuntimeSafety의 핵심이에요. 빌드 모드가 아니라 호출된 스코프가 안전성 검사 여부를 결정해요.
참고로 이 빌트인은 앞으로 @optimizeFor로 대체될 예정이에요.