라이브러리와 링커
▷ 처음 C언어를 배울 때는 완전히 착각을 한 부분이 바로 <stdio.h> 부분이었다. 나는 printf()와 같은 함수의 구현 소스코드가 저 헤더 파일에 있는 줄 착각했다. 그도 당연할 것이, printf() 함수의 구현 소스코드를 본 적이 없었기 때문이다.
▷ 그러나 함수 선언 부인 헤더 파일은 그저 해당 소스코드(텍스트 파일)를 재배치 가능한 파일(오브젝트 파일)로 컴파일하기 위해 존재하는 것일 뿐이다. printf()의 구현체를 발견하질 못했으니 오브젝트 파일 내의 바이너리로 포함할 수 없다. 이러한 미해결 호출 함수의 심볼은 ELF(unix/linux) 혁식이든 COFF(windows)이든 따로 헤더에 저장되고, 이것을 링커가 해결한다.
▷ 호출 가능한 실제 printf() 함수의 구현 바이너리는 라이브러리 형태로 존재한다.
▷ 다양한 라이브러리가 있겠지만 ANSI 표준 C 라이브러리는 보통 C Runtime Libary 라고 부르며, 다양한 라이브러리 파일을 포함하고 있는데, windows 시스템에서 가장 대표적인 것이 msvcrt.dll 파일이다.
▷ "C 런타임 라이브러리"에서 "런타임"이란 말은 프로그램 실행 중에 필수적이고 유용한 함수라는 의미를 강조하기 위한 것이다. 처음에 이걸 나는 동적(Dynamic) 라이브러리와 혼동했는데, 런타임은 동적이라는 말이 아니라, 그냥 프로그램이 실행되면서 호출되는 유용한 함수임을 강조하기 위한 용어일 뿐이고, 실제로 C 런타임 라이브러리는 동적 라이브러리와 정적 라이브러리 모두를 포함하고 있다.
▷ msvcrt.dll 은 MicroSoft Visual C RunTime . Dynamic Link Library 의 약자다. 쉽게 말해 ANSI C 표준 라이브러리 중 메모리 할당이나 printf()와 같이 유용한 함수들의 구현체를 마이크로소프트가 개발하여 동적 라이브러리로 배포한 것이다.
▷ 정확하게 보면 저 파일 이름 안에 Visual C 라는 단어가 포함된 것을 볼 수 있다. 이것은 이 동적 라이브러리는 Microsoft Visual C++ 컴파일러로 빌드할 때 참조된다는 뜻이다.
▷ 이 동적 라이브러리는 C 디스크의 Windows/System32 디렉터리 안에 있다. Windows 디렉터리 안에 있는 이유는 수많은 윈도우즈 프로그램들이 바로 이 msvcrt.dll을 실행 중에 링크하기 때문이다. 왜냐하면 윈도우즈에서 동작하는 많은 프로그램들이 Visual C++ 컴파일러로 빌드되었기 때문이다.
▷ 여담이지만 C:/windows/system32에서 32라는 단어에 속지 말기 바란다. 32비트가 아니라 64비트가 맞다. 하위 호환성을 위해 어쩔 수 없기 남겨둔 디렉터리 이름이다...
▷ 다른 컴파일로 비슷하지만, Visual C++ 컴파일러는 링커를 포함한 통합 빌드 툴인데, 링커는 컴파일된 오브젝트 파일에서 호출되는 각종 함수들이 있는 라이브러리나 다른 오브젝트 파일을 찾을 때 기본적으로 검색하는 경로가 있다. 실행파일이 있는 디렉터리 → windows/system32 → windows → PATH. 뭐 이런 식이다. 따라서, 만약 C:/windows/system32에서 msvcrt.dll을 삭제하면 프로세스의 안전한 동작을 보장하지 못한다.
▷ 새로운 라이브러리 이름과 그 라이브러리가 있는 경로를 링커에게 설정해줄 수 있다. 이 옵션은 Visual Studio에도 있다.
▷