C++에서 DLL을 작성하고 드물지만 소멸자가없는 클래스의 전역 객체를 선언한다고 가정 해 보겠습니다. DLL이 언로드 될 때 소멸자가 호출됩니까?DLL에서 선언 된 전역 변수는 어떻게됩니까?
답변
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 언로드가 정상적이어야합니다.
응용 프로그램이 종료되거나 DLL이 언로드 될 때 호출되어야합니다. 둘 중 빠른 날짜가 적용됩니다. 이것은 컴파일하는 실제 런타임에 따라 다소 달라집니다.
또한 타이밍 및 주문 관련 문제가 있으므로 중요하지 않은 소멸자에게주의하십시오. DLL은 이후 소멸자가 의존하는 DLL 인 경우 을 언로드 할 수 있습니다. 이는 분명히 문제를 일으킬 수 있습니다.
fdwReason = DLL_PROCESS_DETACH 매개 변수가있는 DllMain이 호출되면 DLL이 응용 프로그램에 의해 언로드되었음을 나타냅니다. 이것은 글로벌/정적 객체의 소멸자가 호출되기 전의 시간입니다.
Microsoft에서이 페이지 전역의 DLL 초기화와 파괴의 세부 사항에 간다 : 당신이 .DLL을 링크 할 때 실행됩니다 실제 코드를보고 싶다면
http://msdn.microsoft.com/en-us/library/988ye33t.aspx
이 %ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c
를보십시오.
dll CRT가 유지 관리하는 내부 참조 횟수가 0 일 때 검사에서 소멸자는 _cexit()
을 통해 호출됩니다.
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-카운터가 하나 개의 프로세스가 글로벌 값을 변경 제로
- 1. 루비의 전역 변수는 전역 적으로 어떻게됩니까?
- 2. PHP 전역 선언
- 3. dlclose가 호출 될 때 공유 라이브러리의 전역 변수는 어떻게됩니까?
- 4. MATLAB에서 전역 변수 선언
- 5. dll에서 전역 변수에 액세스
- 6. DLL에서 전역 변수 내보내기
- 7. DLL의 전역 변수는 메모리에 어디에 저장되어 있습니까?
- 8. 파이썬 전역 변수는 스레드로부터 안전합니까?
- 9. VB에서 전역 변수 선언
- 10. C에서 전역 유니온 선언
- 11. 모든 함수의 변수는 전역 변수입니다
- 12. 이 재귀 호출의 로컬 변수는 어떻게됩니까?
- 13. 오라클 트리거 : 선언 전역 변수
- 14. C++ 선언 된 클래스 외부에서 전역 적으로 선언 된 enum을 사용할 수없는 이유는 무엇입니까?
- 15. % d가 printf에서 사용될 때 float 변수는 어떻게됩니까?
- 16. 값이 주어진 람다 식의 변수는 어떻게됩니까
- 17. 자기가 덮어 쓸 때이 경우 변수는 어떻게됩니까?
- 18. 웹 페이지에서 전역 JavaScript 변수는 어디에서 선언해야합니까?
- 19. 코드 이그니 터에서 전역 변수는 어디에 선언해야합니까?
- 20. ASP.NET C# 정적 변수는 전역 변수입니까?
- 21. PHP 전역 변수는 함수에서 찾을 수 없습니다
- 22. 목표 C - 전역 정적 변수는 어디에서 dealloc합니까?
- 23. 전역 변수는 실행 파일의 크기에 어떻게 기여합니까?
- 24. C에서 전역 변수의 범위를 선언 된 파일로 어떻게 제한합니까?
- 25. 선언 된 객체를 전역 QList에 저장하는 것이 안전합니까?
- 26. 전역 변수 선언 위치? .h or.m?
- 27. 컴파일 된 DLL에서 XAML보기
- 28. 일반적으로 선언 된 변수를 전역 변수로 선언 할 때 어떤 이점이 있습니까? 예를 들어
- 29. 내 보낸 dll 함수의 dll에서 전역 데이터에 액세스
- 30. 동적으로로드 된 DLL에서 양식 표시
경우입니다 다른 과정에서 관찰 된 변화? –
@ LB-- : 일반적으로 no : 공유 메모리에 매핑하지 않으면 각 프로세스에 고유 한 전역 변수가 있습니다. 또는 OS 고유의 트릭을 사용하여 해당 DLL을 사용하는 모든 프로세스간에 공유됩니다 (필자는 그렇지 않습니다. Windows의 트릭을 정확히 기억하고 있지만, #pragma declarations, IIRC) – paercebal