50년 전 유닉스, 어떻게 메모리 할당했을까
원제 The lost malloc()
103 포인트댓글 38
Key Point
현재의 C/C++ 메모리 할당 방식이 왜 그렇게 설계되었는지, 그리고 더 나은 대안이 존재했음을 보여주는 컴퓨터 과학 역사의 흥미로운 사례입니다.
핵심 요약
- 1973년 유닉스 V4의 원본 소스를 분석한 고고학적 탐구로, C 언어 초기의 메모리 관리 방식을 추적한다.
- V4 컴파일러는 선형 할당(linear allocator)을 사용했는데, 메모리를 정렬한 후 충분한 공간이 있는지 확인하고 sbrk()로 힙을 확장했으며, 메모리 해제는 전혀 고려하지 않았다.
- Dennis Ritchie가 작성한 malloc.c는 흥미로운 인터페이스를 가졌는데, malloc(coremap, size)와 mfree(coremap, size, pointer) 형태로 명시적 메모리 영역을 전달받았다.
- 이 설계 덕분에 제3자 코드의 메모리 할당을 제한하거나 영역을 버려 한 번에 해제할 수 있었으며, 힙 부패 버그도 덜 심각했을 것이다.
- 이 방식은 코어(32바이트 단위)와 스왑(512바이트 단위) 두 종류의 메모리를 관리하기 위해 설계되었으며, V6까지 유지되다 V8에서 전통적인 malloc()/free()로 전환되었다.
- V7부터 프로그래머들은 ALLOC(x) 같은 매크로로 sizeof 계산을 자동화했고, V8에서는 new(type) 매크로가 등장해 현대의 C++ new 연산자와 유사한 형태였다.
- Stroustrup의 C++ new 연산자는 Simula에서 영감을 받았는데, V8의 이런 매크로들도 Simula에서 파생되었을 가능성이 높다.
- V7에는 garbage() 함수로 자동 가비지 수집을 제공하는 galloc()이 추가되었고, Rob Pike는 gcnew() 매크로로 이를 활용했다.
- 메모리 해제 없는 선형 할당 방식은 프로그램의 단순한 생명주기(할당 → 처리 → 종료)와 메모리 부족 문제, 그리고 수동 메모리 관리의 피로가 결합된 결과로 보인다.
- 결론적으로 유닉스 개발자들은 arena 개념에 매우 가까워 있었지만 시대의 제약과 프로그래밍 패턴의 단순함 때문에 결국 단순한 malloc()/free() 방식으로 진화했다.