Zig의 ArrayList에 포인터 안정성 잠금 도입

Zig: Pointer Stability for ArrayLists

Zig의 표준 라이브러리 `std.ArrayList`에 포인터 안정성 잠금(pointer stability locks)이 추가되었습니다. 이는 2024년 Hash Map 컨테이너에 도입된 기법을 ArrayList로 확장한 것으로, `lockPointers()`와 `unlockPointers()` 호출을 통해 리스트의 재할당으로 인한 포인터 무효화를 방지합니다. 이번 변경으로 개발자는 메모리 안전성 문제를 사전에 감지하고 디버깅할 수 있습니다. 또한 `orderedRemove()`나 `pop()` 같은 순서 변경 작업도 잠금 상태에서 어서션을 발생시켜 잠재적 버그를 조기에 발견할 수 있습니다.

이제 메모리 안전성 문제를 테스트 실패의 원인으로 논리적 버그와 함께 고려해야 한다는 것을 알 수 있습니다.
  1. amluto

    이건 약해 보이네요.

    Rust 같은 언어에서는 컴파일러가 포인터를 자동으로 '잠그기' 때문에 잊을 수가 없습니다.

    C++(그리고 아마 Zig) 같은 언어에서는 이론적으로라도 동적 배열의 저장 공간을 참조하는 반복자와 슬라이스가 저장 공간을 고정하는 일종의 잠금을 보유하도록 할 수 있을 것입니다.

    하지만 이 API는 프로그래머가 포인터를 잠그는 것을 기억해야 하고, 올바른 코드 영역 동안 잠금을 유지해야 합니다. 그리고 제가 보기에는 블로그 게시물의 예제조차도 안정성이 필요한 함수 밖에서 완전히 잠금을 수행하고 있어서, 잠금 범위를 올바르게 설정하는 데 아무런 도움이 되지 않습니다. 타입 시스템조차도 도움이 되지 않습니다. 문제가 되는 parse 함수는 포인터 잠금 ArrayList 매개변수를 원한다고 선언할 수 없습니다.

  2. _bohm

    좋은 기능이긴 한데, 컬렉션의 항목에 대한 안정적인 포인터가 필요하다면 ArrayList가 잘못된 데이터 구조라는 느낌을 지울 수 없네요. 누군가 예를 들어 인덱스를 저장하는 대신 이걸 사용하는 경우를 알려줄 수 있을까요? 또는 Unrolled Linked List(지그에서 0.16에서 제거되기 전에 SegmentedList로 알려졌던 것, 왜 제거되었는지는 모르겠지만)를 사용할 수도 있습니다.

  3. portly

    이것은 언어의 나머지 부분과 일관적이라는 점을 고려하면 매우 합리적입니다. 자신의 프로그래밍 오류를 잡기 위해 코드에 트립와이어를 설정하는 또 하나의 방법입니다. 함수에서 입력과 출력을 검증하기 위해 assert를 사용하는 것과 비슷합니다.

    저는 ArrayList를 많이 사용하기 때문에 코드 전체에 이것을 적용하여 견고하게 만드는 것이 기대됩니다.

    모든 사람이 좋아할 것 같지는 않지만, 그렇다면 아마 다른 명시적인 기능들도 좋아하지 않을 것입니다.

  4. Rendello

    여담: Rust에서 정말 그리웠던 Zig(문법) 기능 중 하나가 두 번째 코드 블록에 나와 있는데, 바로 접두사가 붙은 여러 줄 문자열 리터럴입니다. 예를 들어:

    const text =

    \\This is a long comment

    \\But I can split it among lines arbitrarily

    \\And keep my indentation.

    ;

    저는 이제 Rust 매크로 라이브러리 `docstr` [1]을 사용하기 시작했는데, 같은 일을 합니다:

    const TEXT: &'static str = docstr!(

    /// Now I can do it in Rust, too.

    /// I prefer this style a lot of the time

    /// for long texts.

    );

    심지어 매크로와도 작동합니다 (문서의 예):

    let greeting: String = docstr!(format!

    /// Hello, my name is {name}.

    /// I am {} years old!

    age

    );

    1. https://docs.rs/docstr/latest/docstr/

  5. boricj

    컨테이너 내부의 포인터 변경을 단언하는 것이지 SDL 표면처럼 데이터 구조를 잠그거나 잠금 해제하는 것이 아니라는 것을 이해하는 데 1분 정도 걸렸습니다.

    저는 최근에 std::string을 기반으로 하는 경로의 구성 요소를 반복할 수 있는 사용자 정의 C++ 컨테이너를 구현했습니다. 저는 인덱스와 문자열에 대한 참조만 저장하여, std::string이 수정된 후 재할당되어도 반복자가 무효화되지 않도록 했습니다. 약간의 추가 비용으로 훨씬 덜 오류가 발생하기 쉽습니다.

이 날의 다른 글

2026-08-30