메모리 모델

메모리 모델 (Memory model)

프로그램이 실제로 메모리를 어떻게 바라보는지, 특히 다중 스레드에서 어떤 의미로 "같은 메모리"를 공유하는지 이해하려면 C++ 추상 머신(abstract machine)이 정의하는 메모리 모델부터 알아야 해요.

출처: cppreference

본문

메모리 모델은 C++ 추상 머신을 위한 컴퓨터 메모리 저장의 의미론(semantics)을 정의해요.

C++ 프로그램이 사용할 수 있는 메모리는 하나 이상의 연속된 바이트(byte) 시퀀스예요. 메모리 안의 각 바이트는 고유한 주소(address)를 가져요.

바이트 (Byte)

바이트는 주소를 지정할 수 있는 최소 메모리 단위예요. 연속된 비트들의 시퀀스로 정의되며, 다음 값들을 담기에 충분히 큰 크기예요:

  • 임의의 UTF-8 코드 유닛(256개의 서로 다른 값)의 값, 그리고
  • 기본 실행 문자 집합(basic execution character set)에 속한 임의의 원소 (C++23 이전까지는), 기본 리터럴 문자 집합의 임의 원소의 보통 리터럴 인코딩 (C++23부터)

C와 마찬가지로, C++도 8비트 이상 크기의 바이트를 지원해요.

char, unsigned char, signed char 타입은 저장과 값 표현 모두에 정확히 한 바이트를 사용해요. 바이트 안의 비트 수는 CHAR_BIT 또는 std::numeric_limits<unsigned char>::digits로 알 수 있어요.

메모리 위치 (Memory location)

메모리 위치는 비트 필드(bit-field)가 아닌 스칼라 타입 객체의 객체 표현(object representation)이 차지하는 저장 공간, 또는 길이가 0이 아닌 비트 필드들의 가장 긴 연속 시퀀스 중 하나를 말해요.

참고할 점이 하나 있어요. 참조(reference)나 가상 함수 같은 언어의 여러 기능은, 프로그램이 접근할 수는 없지만 구현이 관리하는 추가적인 메모리 위치를 수반할 수 있어요.

메모리 위치가 어떻게 나뉘는지 예시로 봐볼게요.

struct S
{
    char a;     // 메모리 위치 #1
    int b : 5;  // 메모리 위치 #2
    int c : 11, // 메모리 위치 #2 (계속)
          : 0,
        d : 8;  // 메모리 위치 #3
    struct
    {
        int ee : 8; // 메모리 위치 #4
    } e;
} obj; // 객체 "obj"는 4개의 서로 다른 메모리 위치로 구성된다

여기서 주목할 점은, 서로 다른 비트 필드라 해도 그 사이에 0 길이의 비트 필드가 끼어 있지 않고 인접해 있으면 같은 메모리 위치로 취급한다는 거예요. bc는 둘 다 메모리 위치 #2에 속해 있죠. 이후 [: 0] 비트 필드가 다음 비트 필드를 다른 위치로 나누고, 그 뒤 d가 메모리 위치 #3이 돼요. 그리고 e는 멤버 객체라서 또 별개의 메모리 위치 #4를 차지해요.

결함 보고 (Defect reports)

다음 동작을 바꾸는 결함 보고(defect reports)가 이전에 발표된 C++ 표준에 소급 적용됐어요.

DR 적용 대상 발표 당시 동작 올바른 동작
CWG 1953 C++98 같은 저장 공간을 차지하는 객체들은 서로 다른 메모리 위치로 간주됨 메모리 위치는 이제 저장 공간을 가리킴

더 알아보기