DLL 파일에 대한 링크 는 컴파일 링크 타임에 암시 적으로 또는 런타임에 명시 적으로 발생할 수 있습니다 . 어느 쪽이든 DLL은 프로세스 메모리 공간에로드되고 내 보낸 모든 진입 점을 응용 프로그램에서 사용할 수 있습니다.
런타임에 명시 적으로 사용하는 경우, 사용 LoadLibrary()
하고 GetProcAddress()
수동으로 당신이 호출 할 필요가 함수에 대한 포인터를 DLL을로드하고 얻을.
프로그램이 빌드 될 때 암시 적으로 링크 된 경우 프로그램에서 사용하는 각 DLL 내보내기에 대한 스텁은 가져 오기 라이브러리에서 프로그램에 링크되고 해당 스텁은 프로세스가 시작될 때 EXE 및 DLL로로드 될 때 업데이트됩니다. (예, 여기서 조금 이상 단순화했습니다 ...)
이러한 스텁은 어딘가에서 가져와야 하며 Microsoft 도구 체인에서 가져 오기 라이브러리 라는 특수한 형식의 .LIB 파일에서 가져옵니다 . 필요한 .LIB는 일반적으로 DLL과 동시에 빌드되며 DLL에서 내 보낸 각 함수에 대한 스텁을 포함합니다.
혼란스럽게도 동일한 라이브러리의 정적 버전도 .LIB 파일로 제공됩니다. DLL에 대한 가져 오기 라이브러리 인 LIB가 일반적으로 일치하는 정적 LIB보다 더 작다는 점 (종종 훨씬 더 작음)을 제외하고 구분하는 사소한 방법은 없습니다.
GCC 도구 모음을 사용하는 경우 우연히 DLL과 일치하는 가져 오기 라이브러리가 실제로 필요하지 않습니다. Windows로 포팅 된 Gnu 링커 버전은 DLL을 직접 이해하고 필요한 대부분의 스텁을 즉석에서 합성 할 수 있습니다.
최신 정보
모든 너트와 볼트가 실제로 어디에 있는지 그리고 실제로 무슨 일이 일어나고 있는지 알기에 저항 할 수 없다면 MSDN에는 항상 도움이 될 무언가가 있습니다. Matt Pietrek의 기사 An In-Depth Look into the Win32 Portable Executable File Format 은 EXE 파일의 형식과로드 및 실행 방법에 대한 매우 완벽한 개요입니다. 원래 MSDN Magazine ca에 게재 된 이후로 .NET 등을 포함하도록 업데이트되었습니다. 2002.
또한 프로그램에서 사용하는 DLL을 정확히 파악하는 방법을 아는 것도 도움이 될 수 있습니다. 이를위한 도구는 Dependency Walker (일명 dependent.exe)입니다. 이 버전은 Visual Studio에 포함되어 있지만 최신 버전은 작성자가 http://www.dependencywalker.com/ 에서 구할 수 있습니다 . 링크 타임에 지정된 모든 DLL (초기로드 및 지연로드)을 식별 할 수 있으며 프로그램을 실행하고 런타임에로드하는 추가 DLL을 감시 할 수도 있습니다.
업데이트 2
다시 읽기에 대해 명확히하고 MSDN과의 일관성을 위해 암시 적 및 명시 적 링크 라는 용어를 사용하기 위해 이전 텍스트의 일부를 다시 작성했습니다 .
따라서 라이브러리 함수를 프로그램에서 사용할 수있는 세 가지 방법이 있습니다. 분명한 후속 질문은 "어떻게 어떤 방법을 선택합니까?"입니다.
정적 연결은 프로그램 자체의 대부분이 연결되는 방식입니다. 모든 개체 파일이 나열되고 링커에 의해 EXE 파일로 함께 수집됩니다. 그 과정에서 링커는 모듈이 서로의 함수를 호출 할 수 있도록 전역 심볼에 대한 참조를 수정하는 것과 같은 사소한 작업을 처리합니다. 라이브러리는 정적으로 링크 될 수도 있습니다. 라이브러리를 구성하는 개체 파일은 링커가 필요한 기호를 포함하는 모듈을 검색하는 .LIB 파일의 라이브러리 관리자에 의해 함께 수집됩니다. 정적 링크의 한 가지 효과는 프로그램에서 사용하는 라이브러리의 모듈 만 링크된다는 것입니다. 다른 모듈은 무시됩니다. 예를 들어, 기존 C 수학 라이브러리에는 많은 삼각 함수가 포함되어 있습니다. 그러나 당신이 그것에 대해 링크하고 사용한다면cos()
, 당신의 코드의 사본을 결국하지 않습니다 sin()
또는 tan()
당신은 또한 그 기능을 호출하지 않는 한. 풍부한 기능 세트가있는 대형 라이브러리의 경우 모듈을 선택적으로 포함하는 것이 중요합니다. 임베디드 시스템과 같은 많은 플랫폼에서 라이브러리에서 사용할 수있는 총 코드 크기는 장치에 실행 파일을 저장하는 데 사용할 수있는 공간에 비해 클 수 있습니다. 선택적으로 포함하지 않으면 해당 플랫폼을위한 프로그램 구축 세부 사항을 관리하기가 더 어려울 것입니다.
그러나 실행중인 모든 프로그램에 동일한 라이브러리 의 사본이 있으면 일반적으로 많은 프로세스를 실행하는 시스템에 부담이됩니다. 올바른 종류의 가상 메모리 시스템을 사용하면 동일한 콘텐츠를 가진 메모리 페이지가 시스템에 한 번만 있으면 여러 프로세스에서 사용할 수 있습니다. 이렇게하면 코드가 포함 된 페이지가 가능한 한 많은 다른 실행중인 프로세스에서 일부 페이지와 동일 할 가능성이 높아집니다. 그러나 프로그램이 런타임 라이브러리에 정적으로 링크되면 각기 다른 위치에서 메모리 맵을 처리하는 각기 다른 조합의 기능을 갖게되며, 그 자체로 프로그램이 아닌 경우 공유 가능한 코드 페이지가 많지 않습니다. 프로세스 이상에서 실행됩니다. 따라서 DLL의 아이디어는 또 다른 주요 이점을 얻었습니다.
라이브러리 용 DLL에는 모든 클라이언트 프로그램에서 사용할 수있는 모든 기능이 포함되어 있습니다. 많은 프로그램이 해당 DLL을로드하면 모두 해당 코드 페이지를 공유 할 수 있습니다. 모두가 이깁니다. (글쎄, DLL을 새 버전으로 업데이트하기 전까지는이 이야기의 일부가 아닙니다. Google DLL Hell은 이야기의 측면에 있습니다.)
따라서 새 프로젝트를 계획 할 때 가장 먼저 선택해야하는 것은 동적 연결과 정적 연결 사이입니다. 정적 연결을 사용하면 설치할 파일이 줄어들고 사용하는 DLL을 제 3자가 업데이트하지 않아도됩니다. 그러나 프로그램은 더 크고 Windows 에코 시스템의 좋은 시민이 아닙니다. 동적 연결을 사용하면 설치할 파일이 더 많아지고 사용하는 DLL을 타사에서 업데이트하는 데 문제가있을 수 있지만 일반적으로 시스템의 다른 프로세스에 더 친숙합니다.
DLL의 큰 장점은 주 프로그램을 다시 컴파일하거나 다시 연결하지 않고도로드하고 사용할 수 있다는 것입니다. 이를 통해 타사 라이브러리 공급자 (예 : Microsoft 및 C 런타임)가 라이브러리의 버그를 수정하고 배포 할 수 있습니다. 최종 사용자가 업데이트 된 DLL을 설치하면 해당 DLL을 사용하는 모든 프로그램에서 해당 버그 수정의 이점을 즉시 얻습니다. (일을 깨뜨리지 않는 한. DLL Hell을 참조하십시오.)
다른 장점은 암시 적 로딩과 명시 적 로딩의 차이에서 비롯됩니다. 추가로 명시 적로드 작업을 수행하면 프로그램이 작성되고 게시 될 때 DLL이 존재하지 않았을 수 있습니다. 이를 통해 예를 들어 플러그인을 검색하고로드 할 수있는 확장 메커니즘을 사용할 수 있습니다.
lib /list xxx.lib
및link /dump /linkermember xxx.lib
. 이 스택 오버플로 질문을 참조하십시오 .