힙 관리와 옵셔널 타입
아무도 가리키지 않는 칸을 언어가 알아서 찾아낼 수 있을까?
힙 관리
빈 칸이 떨어지기 전에 되찾아야 합니다
힙의 칸은 요청이 오면 내주고, 다 쓰면 돌려받습니다. 7편에서 본 가비지는 쓰지도 않는데 돌아오지 않는 칸입니다. 이것을 찾아 되돌려 받는 일이 힙 관리(heap management)의 어려운 부분입니다. 방법은 참조 카운터와 마크 스윕, 둘입니다.
힙의 칸을 셀(cell)이라고 부릅니다. 칸 수는 예시입니다.
참조 카운터
나를 가리키는 포인터를 셉니다
참조 카운터(reference counter) 방식은 셀마다 카운터를 두고, 그 셀을 가리키는 포인터의 수를 적습니다. 포인터가 붙으면 늘리고 떨어지면 줄입니다. 0이 되면 아무도 가리키지 않는 것이므로 그 자리에서 회수합니다.
가비지가 생기는 대로 회수하므로 적극적 접근법(eager approach)이라고 합니다.
참조 카운터의 약점
서로 가리키면 0이 되지 않습니다
약점은 셋입니다. 셀마다 카운터를 둘 자리가 들고, 포인터가 바뀔 때마다 카운터를 고치는 시간이 듭니다. 그리고 셀들이 서로를 가리키면 카운터가 0이 되지 않아 회수하지 못합니다.
셋째를 순환 참조라고 합니다. 그림의 A와 B가 그 경우입니다.
마크 스윕
닿는 셀을 가려내고 나머지를 거둡니다
마크 스윕(mark-sweep)은 빈 칸이 모자랄 때 시작합니다. 모든 셀을 가비지로 표시하고, 포인터를 따라가며 닿는 셀의 표시를 지웁니다. 끝으로 표시가 남은 셀을 빈 칸 목록으로 돌려줍니다.
미뤘다가 한꺼번에 하므로 지연 접근법(lazy approach)이라고 합니다. 셀마다 표시용 비트가 하나 더 있습니다.
견주어 보면
조금씩 자주, 또는 몰아서 한 번
참조 카운터는 회수가 조금씩 이뤄져 프로그램이 오래 멈추지 않습니다. 처음의 마크 스윕은 너무 드물게 돌아서, 한 번 돌 때 프로그램이 한참 멈췄습니다. 요즘은 더 자주 돌려 멈춤을 줄입니다. 이것이 점진적 마크 스윕(incremental mark-sweep)입니다.
조각의 길이와 간격은 예시입니다.
옵셔널 타입
값이 없음도 타입에 적습니다
변수에 지금 값이 없다는 것을 나타내야 할 때가 있습니다. 이것을 타입으로 적게 한 것이 옵셔널 타입(optional type)입니다. C#에서는 타입 이름 뒤에 ?를 붙입니다. int? x; 라고 쓰면 x는 정수이거나 null입니다.
C#, F#, Swift가 지원합니다. C#의 참조 타입은 처음부터 null을 가질 수 있어 이미 옵셔널입니다. Swift는 null 대신 nil이라고 씁니다.
다음 편