Lifetime and Ownership
Lifetime and Ownership (수명과 소유권)
포인터가 가리키는 메모리가 사라졌는데 그 포인터를 계속 쓰면 어떻게 될까요? Zig에서는 그 책임을 온전히 프로그래머가 지는 구조예요. 이번에는 포인터의 수명과 소유권을 다루는 기준을 함께 살펴볼게요.
본문
포인터가 가리키던 메모리를 더 이상 사용할 수 없게 됐는데도 그 포인터에 접근하면 안 되는 건, 바로 Zig 프로그래머의 책임이에요. 그리고 슬라이스도 다른 메모리를 참조한다는 점에서 포인터의 한 형태라는 걸 기억해 두면 좋아요.
버그를 막으려면 포인터를 다룰 때 지키면 좋은 관례들이 있어요. 일반적으로 함수가 포인터를 반환한다면, 그 함수의 문서에는 누가 그 포인터를 "소유(own)"하는지가 설명되어야 해요. 이 소유권 개념이 있으면 프로그래머는 그 포인터를 해제(free)해도 되는 때가 언제인지, 그리고 해제해야 할 수도 있는 상황인지 아닌지를 판단할 수 있게 되죠.
예를 들어 함수 문서에 "호출자가 반환된 메모리를 소유합니다(caller owns the returned memory)"라고 적혀 있다면, 그 함수를 호출하는 코드 쪽에서 언제 그 메모리를 해제할지 계획을 세워야 해요. 대개 이런 상황에서는 함수가 Allocator 매개변수를 받아들이는 구조가 되기도 하죠.
포인터의 수명이 더 복잡해지는 경우도 있어요. 예를 들어 std.ArrayList(T).items 슬라이스는, 새 요소를 append하는 등 리스트가 다음 번에 크기를 조정(resize)하기 전까지 유효한 수명을 가져요.
함수와 데이터 구조에 대한 API 문서는 포인터의 소유권과 수명 의미(semantics)를 아주 신경 써서 설명해야 해요. 소유권은 포인터가 참조하는 메모리를 누가 해제할 책임을 질지를 정하고, 수명은 메모리가 접근 불가능해지는 시점을 정하죠. 그 시점을 지나면 불법 동작(Illegal Behavior)이 발생할 수 있어요.