포인터 대신 핸들을 쓰면 메모리 안전성이 높아진다

Handles are the better pointers (2018)

C/C++에서 스마트 포인터 대신 인덱스 핸들을 사용해 메모리 관리를 중앙화하는 방법을 소개한다. 시스템이 배열을 소유하고 외부에는 핸들만 노출하면, 메모리 오염과 가짜 누수, 캐시 미스 같은 문제를 줄일 수 있다. 핸들을 포인터로 변환할 때 범위 검사와 활성 슬롯 검사를 수행해 사용 후 해제 같은 오류를 조기에 잡아낸다. 데이터 지향 아키텍처와 잘 맞는 접근법이다.

핸들을 포인터로 변환할 때마다 시스템은 반환된 포인터가 원래 핸들이 생성될 때 가리키던 항목을 여전히 가리킨다고 보장할 수 있지만, 이 보장은 시간이 지나면서 약화된다. 포인터가 가리키는 항목이 파괴되었거나 기반 메모리가 다른 위치로 재할당되었을 수 있기 때문이다.
  1. boricj

    그건 기본적으로 제가 직장에서 임베디드 프로젝트를 하면서 해온 방식입니다.

    인덱스와 세대(generation)를 사용하는 객체 풀이죠. 원시 포인터를 건드리는 것보다 훨씬, 정말 훨씬 쉽고, shared_ptr/weak_ptr보다 저렴하며, 무언가를 삭제할 때 정리 작업이 필요 없습니다. 저장된 세대가 새 객체의 세대와 일치하지 않을 테니까요. 인스턴스화할 때도 세대를 증가시키면(그래서 짝수 세대만 살아 있도록) 기본 생성이 가능하게 만들 수도 있고, C++의 고수준 추상화 뒤에 이 모든 것을 숨길 수도 있습니다.

    다만 제가 이런 기법을 알게 된 건 2000년대 비디오 게임 아키텍처에서였습니다. GTA: Vice City 같은 게임들이 이걸 쓴다고 알려져 있죠.

  2. nickwanninger

    제 박사 논문이 바로 이 주제에 관한 것이고, 몇 년 전에 LLVM을 통해 비관리 언어(C/C++)에서 핸들 기반 메모리 지원을 다룬 ASPLOS 논문도 있었습니다: https://nickw.io/papers/asplos24-alaska.pdf

    거기서 관찰한 오버헤드는 놀랍게도 소프트웨어 핸들을 사용함으로써 생기는 명령어 및 분기 오버헤드에서만 나온 것입니다. 저는 이를 하드웨어에서 구현하는 작업을 진행 중이고, 오버헤드는 훨씬 더 낮습니다.

  3. Conscat

    저는 제 C++ 프로젝트에서 이 방식으로 프로그래밍해보려고 진지하게 시도했는데(대부분 이 글 덕분이었습니다), 개인적으로 핸들을 사용하려는 모든 곳에 이 리소스의 소유자를 함께 들고 다녀야 해서 극도로 번거롭다고 느꼈습니다. 그것 자체가 서로 다른 함수에 있을 때 성능을 악화시킬 수 있고, 제네릭 프로그래밍을 어렵게 만들며 그런 코드는 템플릿을 더 많이 쓰게 되고, 리팩터링하기도 어려웠습니다.

    하지만 이건 아주 저수준 프로젝트였고, Floooh는 아마 최종 사용자 애플리케이션을 더 염두에 두었을 거라고 생각합니다.

이 날의 다른 글

2026-11-03