it-swarm-ko.tech

DLL에 선언 된 전역 변수는 어떻게됩니까?

C++에서 DLL을 작성하고 사소하지 않은 소멸자가있는 클래스의 전역 객체를 선언한다고 가정 해 봅시다. DLL 언로드?

38
Dima

Windows C++ DLL에서는 DLL_PROCESS_ATTACH를 사용하여 DllMain을 호출하기 직전에 모든 전역 개체 (정적 클래스 멤버 포함)가 생성되며 DLL_PROCESS_DETACH를 사용하여 DllMain을 호출 한 직후에 소멸됩니다.

이제 세 가지 문제를 고려해야합니다.

0-물론 전역 비 const 객체는 사악합니다 (그러나 이미 알고 있으므로 멀티 스레딩, 잠금, 신 객체 등은 언급하지 마십시오)

1-객체 또는 다른 컴파일 단위 (예 : CPP 파일)의 생성 순서가 보장되지 않으므로 두 객체가 두 개의 다른 CPP로 표시되는 경우 객체 A가 B보다 먼저 생성되기를 기대할 수 없습니다. B가 A에 의존하는 경우 중요합니다. 해결책은 동일한 컴파일 단위 내에서와 같이 모든 전역 객체를 동일한 CPP 파일로 이동하는 것입니다. 객체의 순서는 구성 순서 (및 순서의 역순)입니다. 파괴의)

2-DllMain에서 금지 된 사항이 있습니다. 그러한 것들도 생성자에서 금지되어 있습니다. 따라서 무언가를 잠그지 마십시오. 이 주제에 관한 Raymond Chen의 훌륭한 블로그를 참조하십시오.

http://blogs.msdn.com/oldnewthing/archive/2004/01/27/63401.aspx

http://blogs.msdn.com/oldnewthing/archive/2004/01/28/63880.aspx

이 경우 게으른 초기화는 흥미로울 수 있습니다. 클래스는 메소드 중 하나를 호출 할 때까지 "초기화되지 않은"상태 (내부 포인터는 NULL, 부울은 false 등)로 유지됩니다. main (또는 main의 자손 함수 중 하나) 내부에서 해당 객체를 사용하면 DllMain을 실행 한 후에 호출되기 때문에 괜찮습니다.

3-물론 DLL A의 일부 전역 객체가 DLL B의 전역 객체에 의존하는 경우) DLL 로딩 순서 및 그에 따른 종속성이 경우 직접 또는 간접 순환 종속성이있는 DLL은 골치 아픈 양의 두통을 유발할 수 있습니다. 가장 좋은 해결책은 순환 종속성을 끊는 것입니다.

추신 : C++에서는 생성자가 던질 수 있으며 DLL 로딩의 중간에 예외를 원하지 않으므로 전역 객체가 예외없이 예외를 사용하지 않아야합니다. 올바르게 작성된 소멸자가 던져 질 권한이 없으므로 DLL 언로드는 괜찮습니다.).

37
paercebal

Microsoft의이 페이지는 DLL 전역 초기화 및 삭제에 대한 세부 정보를 제공합니다.
http://msdn.Microsoft.com/en-us/library/988ye33t.aspx

6
Mark Ransom

.dll을 연결할 때 실행되는 실제 코드를 보려면 %ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c를보십시오.

검사에서 dll CRT가 유지 관리하는 내부 참조 횟수가 0에 도달하면 소멸자가 _cexit()을 통해 호출됩니다.

4
MSN

응용 프로그램이 종료되거나 DLL 중 하나가 먼저 언로드 될 때 호출되어야합니다. 이는 컴파일하는 실제 런타임에 따라 다소 다릅니다.

또한 타이밍 및 순서 문제가 있기 때문에 사소한 소멸자를 조심하십시오. DLL 언로드 될 수 있습니다. after a DLL 소멸자가 의존하고있어 분명히 문제가 발생할 수 있습니다.

3
Philip Rieck

FdwReason = DLL_PROCESS_DETACH 매개 변수가있는 DllMain이 호출되면 DLL가 응용 프로그램에 의해 언로드됩니다. 이는 전역/정적 오브젝트의 소멸자가 호출되기 전의 시간입니다.

1
INS

확장명이 * .exe 인 Windows 이진 이미지 파일에서 * .dll은 PE 형식 에 있습니다. 이러한 파일에는 진입 점이 있습니다. 다음과 같은 dumpbin 도구로 볼 수 있습니다

dumpbin/headers dllname.dll

Microsoft의 C 런타임을 사용하는 경우 진입 점은 * CRTStartup 또는 * DllMainCRTStartup과 같습니다.

이러한 함수는 c 및 c ++ 런타임의 초기화를 수행하고 실행을 각각 (main, WinMain) 또는 DllMain에 위임합니다.

Microsofts VC 컴파일러를 사용하는 경우 VC 디렉토리에서이 함수의 소스 코드를 볼 수 있습니다.)

  • crt0.c
  • dllcrt0.c

DllMainCRTStartup은 dll 언로드 중에 알림 DLL_PROCESS_DETACH를 검색 할 때 일반적인 시나리오에서 .data 섹션에서 전역 변수를 초기화/초기화하는 데 필요한 모든 것을 처리합니다. 예를 들면 다음과 같습니다.

  • 프로그램의 시작 스레드의 메인 또는 WinMain은 제어 흐름을 반환합니다.
  • 명시 적으로 FreeLibrary를 호출하고 use-dll-counter가 0입니다.
1
bruziuz