2008-09-16 8 views

답변

33

Windows C++ DLL에서 모든 전역 개체 (클래스의 정적 멤버 포함)는 DLL_PROCESS_ATTACH가있는 DllMain 호출 바로 전에 생성되며 DLL_PROCESS_DETACH가있는 DllMain 호출 직후에 소멸됩니다. 물론, 글로벌 const가 아닌 객체가 악 (하지만 당신이 이미 알고, 그래서 멀티 스레딩, 잠금, 신 객체 등 mentionning 피할 것 -

0 : 이제

, 당신은 세 가지 문제를 고려해야합니다)

1 - 개체 또는 다른 편집 단위 (즉, CPP 파일)의 구성 순서가 보장되지 않으므로 두 개체가 서로 다른 두 인스턴스에 인스턴스화 된 경우 B보다 먼저 개체 A가 생성되기를 기대할 수 없습니다. CPP. 이것은 B가 A에 의존하는 경우 중요합니다. 동일한 CPP 파일에서 모든 전역 개체를 이동하는 것입니다. 동일한 컴파일 단위 내에서 개체의 인스턴스화 순서는 구성 순서 (및 순서의 역함수)가됩니다 파괴의)

2 - DllMain에서 금지 된 사항이 있습니다. 이러한 것들은 아마도 생성자에서 금지되어있을 것입니다. 따라서 무언가를 잠그지 마십시오. 주제에 레이몬드 첸의 훌륭한 블로그를 참조하십시오 :이 경우

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

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

가, 게으른 초기화가 재미있을 수 : 클래스 내부 포인터가 NULL입니다 (에 "초기화되지 않은"상태로 유지, 부울은 틀린 것입니다. 무엇이든간에) 당신이 그들의 메소드 중 하나를 호출 할 때까지, 그들은 스스로를 초기화 할 것입니다. 메인 (또는 메인의 자손 함수 중 하나) 내부에서 이러한 객체를 사용하면 DllMain을 실행 한 후에 호출되기 때문에 괜찮을 것입니다.

3 - 물론 DLL A의 일부 전역 객체가 DLL B의 전역 객체에 의존하는 경우 DLL로드 순서 및 의존성에 대해 매우주의해야합니다.이 경우 직접적 또는 간접적 인 순환 의존성을 가진 DLL로 인해 미친듯한 두통을 유발할 수 있습니다. 가장 좋은 해결책은 원형 종속성을 깨는 것입니다.

P. : C++에서 생성자가 throw 할 수 있으며 DLL로드 중에 예외를 원하지 않으므로 전역 개체가 예외를 사용하지 않도록주의해야합니다. 제대로 작성된 소멸자가 던질 수있는 권한이 없기 때문에이 경우 DLL 언로드가 정상적이어야합니다.

+2

경우입니다 다른 과정에서 관찰 된 변화? –

+2

@ LB-- : 일반적으로 no : 공유 메모리에 매핑하지 않으면 각 프로세스에 고유 한 전역 변수가 있습니다. 또는 OS 고유의 트릭을 사용하여 해당 DLL을 사용하는 모든 프로세스간에 공유됩니다 (필자는 그렇지 않습니다. Windows의 트릭을 정확히 기억하고 있지만, #pragma declarations, IIRC) – paercebal

3

응용 프로그램이 종료되거나 DLL이 언로드 될 때 호출되어야합니다. 둘 중 빠른 날짜가 적용됩니다. 이것은 컴파일하는 실제 런타임에 따라 다소 달라집니다.

또한 타이밍 및 주문 관련 문제가 있으므로 중요하지 않은 소멸자에게주의하십시오. DLL은 이후 소멸자가 의존하는 DLL 인 경우 을 언로드 할 수 있습니다. 이는 분명히 문제를 일으킬 수 있습니다.

1

fdwReason = DLL_PROCESS_DETACH 매개 변수가있는 DllMain이 호출되면 DLL이 응용 프로그램에 의해 언로드되었음을 나타냅니다. 이것은 글로벌/정적 객체의 소멸자가 호출되기 전의 시간입니다.

4

%ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c를보십시오.

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

1

Windows에서 * .exe, * .dll 확장명을 가진 이진 이미지 파일은 PE format 입니다. 이러한 파일에는 Entry Point가 있습니다. * CRTStartup 같은 당신이 마이크로 소프트의 C 런타임을 사용하는 경우 당신은/헤더

을 dllname.dll

DUMPBIN 같은 DUMPBIN 도구를 볼 수 있습니다, 당신의 시작점이 될 것입니다 무언가 또는 * DllMainCRTStartup이

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

당신은 당신이 당신 VC 디렉토리에서이 기능의 소스 코드를 볼 수 있습니다 마이크로 소프트의 VC 컴파일러를 사용하는 경우 :

  • crt0.c
  • dllcrt0.c

DllMainCRTStartup이 과정 모든 것 dll 언로드 중에 DLL_PROCESS_DETACH 알림을 검색 할 때 일반 시나리오에서 .data 섹션에서 전역 변수를 초기화/제거해야합니다. 예를 들어 :

  • 주 또는 프로그램 반환의 시작 스레드의 WinMain

  • 흐름을 제어 당신은 명시 적으로는, FreeLibrary를 호출하고 사용-DLL-카운터가 하나 개의 프로세스가 글로벌 값을 변경 제로
관련 문제