My 요약 : 아래 색칠한 부분 참고



출처: http://sweeper.egloos.com/1792751


Static & Dynamic Library



1. Static library

Dynamic (linking) library (흔히 얘기하는 DLL)을 설명하기 위해 간단하게 정리한다.

특정 기능의 라이브러리를 static 하게 제작한다는 것은 link 단계에서
라이브러리(*.lib 파일)를 실행 바이너리에 포함시킨다는 얘기이다.

즉, 라이브러리의 동작 코드가 이를 사용하는 실행 바이너리 속에 
포함되기 때문에 별도의 추가 작업없이, 그리고 독립적으로(실행 바이너리만으로...)
라이브러리 함수들을 사용할 수 있다.

하지만, 정적 라이브러리를 사용하는 프로그램이 늘어나면 날수록
불필요하게 실행 파일들의 크기가 커지며, 
라이브러리가 동시에 여러 실행 바이너리에 포함되어 실행되는 경우
메인 메모리의 공간 활용 효율이 떨어지는 등 multiple-caller program이 존재하는 경우 그다지 바람직하지 않다.

정적 라이브러리를 사용하기 위해서는 프로젝트 설정의 Link 옵션에 
라이브러리를 추가해 주거나 아래의 #pragma 지시자를 사용하면 된다.

#pragma comment(lib, "NAME.lib")


2. Dynamic (linking) library : DLL

말 그대로 "동적으로 링크하여 사용하는 라이브러리" 이다.

동적 라이브러리는 이를 사용하고자 하는 실행 바이너리에서 
필요시 사용할 수 있도록 최소한의 정보만 포함하여 링크하거나,
아예 독립적으로 DLL을 로드/사용/해제할 수 있다.

1) Implicit linking

DLL을 구현하고 컴파일하고 나면 static library와는 다르게  output file이 2개 생성된다.
하나는 *.lib 파일이고 하나는 *.dll 파일이다.
여기서 *.lib 파일은 static library의 *.lib 파일과는 전혀 다르다.

Static library의 *.lib 파일은 라이브러리 전체 코드를 포함하는 바이너리이며,
DLL의 *.lib 파일은 DLL이 제공하고자 하는 함수 정보(함수명)을 가지는 정보 파일이다.

DLL의 *.lib 파일을 이용하여 링킹하는 것을 암시적 링킹(implicit linking)이라고 한다.
실행 바이너리를 링크 단계에서 실행 바이너리의 *.obj 파일들과 DLL의 *.lib 파일을
함께 링크하여 이 정보를 토대로 runtime에 DLL의 함수 코드를 참조하게 되는 것이다.
(한 줄로 요약하면 *.lib 파일은 링크시 필요하고, *.dll 파일은 실행시 필요하다)

정적 라이브러리를 사용할 때와 같이 프로젝트 설정의 Link 옵션에 
라이브러리를 추가해 주거나 아래의 #pragma 지시자를 사용하면 된다.

#pragma comment(lib, "NAME.lib")

2) Explicit linking

명시적 링킹에서는 *.lib 파일이 필요하지 않다.
실행 바이너리 링크 단계에서 DLL의 함수 정보가 필요하지 않기 때문이다.

명시적 링킹에서 사용되는 세 가지 함수와 역할은 다음과 같다.

1. LoadLibrary : 필요한 DLL을 프로세스 가상 메모리에 맵핑한다.
2. GetProcAddress : DLL 함수의 포인터를 획득한다.
3. FreeLibrary : 프로세스 가상 메모리에서 DLL을 반환한다.

프로세스는 내부적으로 DLL의 레퍼런스 카운트를 계산한다.
LoadLibrary 호출시 DLL의 (프로세스) 레퍼런스 카운트는 1씩 증가하고,
FreeLibrary 호출시 레퍼런스 카운트가 1씩 감소한다. 
레퍼런스 카운트가 0이 될 때 해당 DLL은 프로세스 가상 메모리에서 해제된다.

여기서 주의할 점이 물리 메모리가 아닌 가상 메모리에서의 반환(해제)라는 것이다.
레퍼런스 카운트는 각 프로세스 내부의 호출 회수이지,
전체 프로세스 간의 호출 회수가 아니라는 것이다.

이러한 레퍼런스 카운트를 두는 이유는 프로그램 실행 중에 
DLL을 가상 메모리에 할당, 해제할 수 있도록 하기 위함이다.
(Implicit linking 방식에서는 이러한 장점을 얻을 수 없다.)

정리해서 명시적 링킹의 장점을 세 가지 정도 정리해 보면...

1. DLL이 필요한 시점에서 로딩하고, 불필요해지면 반환하기 때문에 메모리가 절약된다.
2. 프로그램 실행 중에 DLL 교체 및 선택이 가능하다.
3. 암시적 링킹은 프로그램 실행 전에 필요한 모든 DLL을 메모리에 로딩한다.
때문에 실행까지 걸리는 시간이 길어질 수 있다. 반면에 명시적 링킹은 필요한 순간에
하나씩 DLL을 로딩할 수 있기 때문에 그만큼 실행까지 걸리는 시간이 짧고, 
DLL 로딩에 걸리는 시간을 분산시킬 수 있다.

뭐 위와 같이 명확한 장점들이 있음에도 불구하고 암시적 링킹이 더 선호되는 경우가 있는데,
이는 사용하기 쉽기 때문이다. 코드가 간결해 진다는 것, 사용하기 쉽다는 것은
대부분의 경우에 있어서의 성능보다도 더 큰 장점을 지니는 것이 아닌가 생각해 본다.

Posted by 세모아