들어가기 앞서,
네임 맹글링(Name Mangling) #
코드에서 선언한 함수나 변수의 이름을 컴파일러가 컴파일 단계에서 일정한 규칙을 가지고 변형하는 것. 맹글링을 영어 사전에서 찾아보면 "난도질 하다", "형태를 알 수 없게 짓이기다"라고 되어 있는데 C++는 컴파일러 단계에서 컴파일러가 함수나 변수 이름을 크게 바꾼다. C는 컴파일러의 이 작업을 이름 장식(Name Decoration)이라고 표현하는데 이름 앞, 뒤에 간단한 규칙을 가진 문자를 붙이는 정도로 맹글링 수준은 아니다.
맹글링이 필요한 이유 #
C에서는 링커가 함수를 이름으로만 구분하고, C++에서는 매개변수까지 사용해서(시그니처) 구분한다. 즉, 똑같은 이름의 함수라도 매개변수에 따라 링커는 달리 구분한다. 같은 이름의 함수가 여럿 존재할 때 어떤 함수를 호출하는지 구분해서 링크하기 위해 이름 외에 매개변수까지 사용해서 컴파일러는 이름을 변형(맹글링)한다.
이와 같은 C++에서는 추가된 기능인 함수 오버로딩의 지원과 함께, 클래스 상속의 경우로 확대하게 되면 이름과 매개변수까지 똑같은 함수가 클래스 안에 여러개 존재하게 된다. 이는 다형성 지원을 위해 객체지향 언어에서는 엄청나게 중요한 기능이고 컴파일러는 함수가 속한 클래스까지 반영해서 함수 이름을 만들어야 한다. 이를 지원하기 위해서 네임 맹글링 작업이 존재할 수 밖에 없다.
기타 #
네임 맹글링은 정형화된 규칙이 없고 C++ 컴파일러 회사마다 규칙이 다르다. 역어셈블리 작업 중 네임 맹글링된 변수의 원형을 알아보기 위해 컴파일러 문서를 구해볼 경우가 생길지도 모른다. 이런 경우를 대비해서 컴파일러 제조사마다 디맹글링을 지원해주는 유틸리티가 존재한다. VC++의
undname
, GNU 컴파일러의 nm --demangle
옵션 등이 있다. extern "C" = C 이름 장식을 사용하겠다. 즉, "네임 맹글링을 하지 않겠다"의 의미.
extern 키워드 #
extern은 링크 규칙(linkage)을 정하기 위한 키워드이다. 함수와 변수는 static, const 등에 의해 모듈(.cpp 파일) 안에서만 참조할 수 있는 internal linkage 를 갖는 경우를 제외하고 기본적으로 external linkage 를 갖게 되어서 다른 모듈에서 링크할 수 있게 된다.
외부 모듈의 함수나 변수를 링크 하려면 extern 키워드를 사용해 링크하려는 대상을 찾을 수 있도록 해준다. C++에서 그냥 extern 만 사용하면 extern "C++" 과 같은 뜻이다. 그리고 extern "C" 를 적용하면 이 이름을 찾아 링크하려는 녀석이 C라는 의미다. 따라서 C 이름 장식을 사용하게 된다. gcc는 gcj를 통해 자바와 링크할 수 있어 extern "Java"도 가능하다. gcj로 컴파일된 자바 모듈을 찾아서 링크할 수 있도록 하라는 의미다. 기술적/실용적 이유에서 사실상 대부분 컴파일러가 extern "C++"과 extern "C"만 지원하지만, extern "X"의 "X" 자리에 어떤 언어든, 또는 어떤 링크 규칙이든 들어올 수 있다.
extern "C" #
C++ 네임 맹글링을 하면 외부 C 모듈에서 링크할 수 없다. C는 C++ 네임 맹글링을 모르기 때문에. 그리고 서로 다른 C++ 컴파일러로 컴파일된 모듈 역시 위에서 언급했던 대로 컴파일러 제조사마다 네임 맹글링 방법이 달라지는 이유로 링크할 수 없다. 그래서 DLL과 같이 컴파일된 이미지를 상호 간에 사용해야할 경우 extern "C" 를 사용하여 C 언어 기본 이름 장식 형식으로 컴파일 하도록 만들어 서로 호환되게끔 사용하는 것이다. 이것이 extern "C" 의 의미다.
참고