DLL의 데이터를 응용 프로그램 또는 다른 DLL과 공유하려면 어떻게 합니까?
업데이트: 2007년 11월
Win32 DLL은 호출 프로세스의 주소 공간에 매핑됩니다. 기본적으로 DLL을 사용하는 각 프로세스에는 모든 DLL의 전역 및 정적 변수에 대한 자체 인스턴스가 있습니다. DLL이 다른 응용 프로그램이 로드한 DLL의 다른 인스턴스와 데이터를 공유해야 할 경우 다음 방법 중 하나를 사용할 수 있습니다.
data_seg pragma를 사용하여 명명된 데이터 섹션을 만듭니다.
메모리 매핑 파일을 사용합니다. MSDN Lib의 "Win32에서 메모리 매핑 파일 관리" 설명서를 참조하십시오.
다음은 data_seg pragma 사용 예입니다.
#pragma data_seg (".myseg")
int i = 0;
char a[32]n = "hello world";
#pragma data_seg()
data_seg를 사용하여 새로운 명명된 섹션(이 예제에서는 .myseg)을 만들 수 있습니다. 일반적인 사용 방법은 명확하게 데이터 세그먼트 .shared를 호출하는 것입니다. /SECTION:.MYSEC,RWS 링커 옵션을 사용하거나 .def 파일의 새로운 명명된 데이터 섹션에 대해 올바른 공유 특성을 지정해야 합니다.
공유 데이터 세그먼트를 사용하기 전에 몇 가지 제한 사항을 고려해야 합니다.
공유 데이터 세그먼트의 변수는 정적으로 초기화되어야 합니다. 위의 예제에서 i는 0으로 초기화되며 a는 hello world로 초기화된 32문자입니다.
모든 공유 변수는 지정된 데이터 세그먼트의 컴파일된 DLL에 있어야 합니다. 배열이 크면 DLL도 커집니다. 초기화된 모든 전역 변수에 대해 해당됩니다.
프로세스 관련 정보를 공유 데이터 세그먼트에 저장하지 마십시오. 대부분의 Win32 데이터 구조나 값(예: HANDLE)은 단일 프로세스의 컨텍스트 내에서만 유효합니다.
각 프로세스는 자체 주소 공간을 얻습니다. 공유 데이터 세그먼트에 포함된 변수에는 포인터가 저장되지 않는다는 점에 주목할 필요가 있습니다. 포인터는 한 응용 프로그램에서는 절대적으로 유효하지만 다른 응용 프로그램에서는 그렇지 않습니다.
각 프로세스의 가상 주소 공간 내의 다른 주소로 DLL 자체가 로드될 수 있습니다. DLL이나 다른 공유 변수에서 함수에 대한 포인터를 사용하는 것은 안전하지 않습니다.
뒤의 세 가지 항목은 메모리 매핑된 파일 및 공유 데이터 세그먼트에 적용됩니다.
메모리 매핑된 파일의 시작 위치를 알 수 없으므로 메모리 매핑된 파일이 공유 데이터 섹션보다 유용합니다. 개발자는 공유 메모리 내부에 있는 모든 데이터에서 "공유 메모리 섹션의 시작 위치를 기준으로 하는 오프셋"을 사용하여 포인터와 유사한 동작을 구현할 수 있습니다. 빠르고도 간편한 작업을 위해 __based 포인터가 강력히 권장됩니다. 그러나 기준(또는 메모리 매핑된 파일의 시작 위치)은 각 프로세스마다 달라질 수 있으므로 __based 포인터의 기준을 저장하는 변수 자체는 공유 메모리에 있을 수 없습니다.
이러한 제한이 C++ 클래스에서는 중요한 의미를 갖습니다.
가상 함수를 사용하는 클래스에는 항상 함수 포인터가 있습니다. 가상 함수를 사용하는 함수는 공유 데이터 세그먼트에 저장될 수 없으며 메모리 매핑된 파일에도 저장될 수 없습니다. 이 점은 MFC 클래스나 MFC에서 상속된 클래스에게 중요합니다.
통계 데이터 멤버는 전역 변수와 동등한 변수로 구현됩니다. 따라서 각 프로세스에는 해당 클래스의 정적 데이터 멤버에 대한 자체 복사본이 있습니다. 정적 데이터 멤버를 사용하는 클래스는 공유될 수 없습니다.
공유 데이터 세그먼트의 초기화 요구 사항으로 인해 C++ 클래스에서 특별한 문제가 제기됩니다. 공유 데이터 세그먼트에 CTest Counter(0); 같은 문이 있으면 Counter 개체는 DLL을 로드하는 각 프로세스에서 초기화되어 매번 개체 데이터가 0으로 됩니다. 링커가 DLL을 만들 때 초기화하는 내장 데이터 형식과는 다릅니다.
이러한 제한 때문에 프로세스 간에 C++ 개체를 공유하는 것은 바람직하지 않습니다. 일반적으로 C++를 사용하여 프로세스 간에 데이터를 공유하려면, 데이터를 공유하기 위해 내부적으로 메모리 매핑된 파일을 사용하는 클래스를 작성하되 클래스 인스턴스는 공유하지 마십시오. 이런 클래스를 개발할 때는 신중해야 하지만 이런 방식으로 응용 프로그램 개발자는 데이터 공유에 의한 부작용을 완벽하게 제어할 수 있습니다.
명명된 데이터 섹션을 만드는 방법에 대한 자세한 내용은 https://support.microsoft.com의 기술 자료 문서를 참조하십시오.
"How to Share Data Between Different Mappings of a DLL"(Q125677)
"Specifying Shared and Nonshared Data in a DLL"(Q100634)
"Sharing All Data in a DLL"(Q109619)
"Memory in Shared Code Sections Is Not Shared Across Terminal Server Sessions"(Q251045)