[C++] internal linkage와 external linkage의 차이

보통 프로그램은 하나의 소스가 아닌 여러 개의 소스로 구성된다. 이 소스를 C++ 표준에서는 translation unit이라고 하고, 소스를 컴파일하는 과정을 translation이라고 한다. translation의 마지막 단계는 link인데, 이 과정을 제외하고는 모든 translation은 독립적으로 진행된다. 이때 translation unit 내에서 이름이 어느 범위까지 사용될 수 있는가를 정하는 것이 지난번 글에서 설명한 스코프이다.

이번에 설명할 linkage는 같은 이름이 같은 entity를 지칭하는 범위를 정하는 것이다. 각 이름은 어떤 linkage를 가지는가에 따라서 translation의 마지막 단계에서 어떻게 link 될지 달라진다. linkage에는 internal linkage와 external linkage 두 가지 종류의 linkage가 있다. 하지만 모든 이름이 linkage를 가지는 것은 아니다. 우선은 linkage를 가지지 않는 이름에 대해 알아보도록 하겠다.

no linkage

영어로는 has no linkage라고 하여 has internal/external linkage와 자연스럽게 대구가 된다. 하지만 한국어로 말하면 no linkage를 가진다고 하는 것은 어색하므로 그냥 linkage를 가지지 않는다고 하는 것이 적당해 보인다.

어찌 됐든 모든 이름이 linkage를 가지는 것은 아니다. block scope에 선언된 이름은 함수와 extern으로 선언된 변수를 제외하면 전부 linkage를 가지지 않는다. 따라서 함수 안에서 선언한 로컬 클래스, enumeration, enumerator, 타입 등은 전부 linkage를 가지지 않는다.

linkage를 가지지 않는 이름은 선언된 스코프에서밖에 접근할 수 없고, 스코프 밖에서 그 이름을 다시 사용해도 그건 다른 entity를 지칭하는 것이 된다. static 한정자를 사용하여 static storage에 저장한 경우도 마찬가지다. 이는 block scope에 선언된 이름은 함수 안에서만 사용하기 위한 것이기 때문이다.

internal linkage

internal linkage를 가지는 이름은 외부 translation unit으로 공개되지 않는다. internal linkage를 가지는 이름은 다음과 같다.

  1. namespace scope에 선언된 static specifier가 붙은 이름
  2. namespace scope에 선언된 anonymous union의 데이터 멤버
  3. namespace scope에 선언된 const 혹은 constexpr이 붙고 volatile은 아닌 변수
  4. unnamed namespace에 선언된 모든 이름

internal linkage를 가지는 이름은 두 개 이상의 translation unit에서 공유할 수 없다. 따라서 다른 translation unit에서 같은 스코프에 같은 이름으로 선언된 변수나 함수가 있어도 물리적으로 이는 다른 객체를 가리킨다. 따라서 헤더 파일에 internal linkage를 가지는 mutable 한 객체를 선언한 경우 읽는 사람이 코드를 잘못 읽을 여지를 줄 수 있기에 namespace scope에 선언되는 mutable 한 객체는 헤더 파일에 선언하지 않는 것이 좋다. 만약 반드시 헤더 파일에 선언해야 한다면, external linkage를 가지도록 해야 한다.

external linkage

위에서 설명한 internal linkage와 다르게 external linkage를 가지는 이름은 다른 translation unit과 공유된다. 다시 말해서 어떤 이름이 external linkage를 가진다면 그 이름은 서로 다른 translation unit에서 사용되더라도 같은 내용을 가져야 한다.

  1. namespace scoep에 선언 된 이름 중 internal linkage가 아닌 이름.
  2. block scope에 선언된 함수
  3. block scope에 선언된 변수 중에서 extern으로 선언된 변수

external linkage를 가지는 이름은 위와 같다. 만약 external linkage로 선언된 이름이 함수일 경우 이 함수는 다른 translation unit에서 같은 코드 영역을 가리키게 되며, 그 함수에서 선언된 static storage나 thread_local storage에 저장되는 지역 변수도 공유하게 된다. 만약 그 이름이 객체를 지칭하는 변수라면, 다른 translation unit에서 사용될 때 같은 메모리를 여역을 공유하며, 따라서 한 translation unit에서 객체의 값을 수정하면 다른 translation unit에서도 수정된 값을 보게 된다. 또한, external linkage로 선언된 클래스가 있다면 그 클래스의 멤버 함수들과 전역 멤버 변수들도 전부 external linkage를 가지게 된다.

댓글

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

RAII는 무엇인가

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API