DllMain에서 하지 말아야 할 것들
저장소/VC++야호~~~
FreeLibrary를 할 때 리턴이 안 되는 문제가 있었다.
아오! 대체 왜 그러는지 찾는데 몇시간이 걸린건가 @_@
원인은 CoUninitialize 호출 후 반환되지 않는 문제로 인한 것이었다.
MSDN에 CoUninitialize를 살펴보면 아래와 같은 내용이 있다.
Because there is no way to control the order in which in-process servers are loaded or unloaded, do not call CoInitialize, CoInitializeEx, or CoUninitialize from the DllMainfunction.
CoInitialize 처리는 DllMain에서 하지 않았지만 CoUninitalize는 DllMain의 DLL_PROCESS_DETATCH 에서 처리했던게 문제였다.
사실 중간에 CoInitialize/CoUninitialize를 사용했다는 것을 몰랐던 내 문제지만 ㅋㅋ
객체 해제 과정을 따로 처리한 다음에 DllMain에서는 아무 것도 처리하지 않게 만들면 쉽게 해결 가능할 것 같은데
안 해봐서 모르니 일단 패스.
원인을 찾다보니 DLL지옥 관련된 여러 내용들이 있는 것 같다.
정리를 잘 해주신 분들이 있으니까 참고하도록 하자.
참고 1 : http://ancdesign.tistory.com/43
참고 2 : 신영진님의 옛날 블로그 (http://www.jiniya.net/tt/788)
다음 내용은 신영진님의 블로그에서 낼름 복사한 것이다. (혹시 없어질까봐 ^^;)
경고!!!
DllMain에서 다음 작업들은 절대로 하지 말 것.
- LoadLibrary, LoadLibraryEx 호출. 데드락이나 크래시를 유발한다.
- 다른 스레드와 동기화. 데드락을 유발한다.
- 로더 락을 획득하려는 코드가 가지고 있는 동기화 오브젝트를 획득하려는 시도. 데드락을 유발한다.
- CoInitializeEx를 사용한 COM 스레드 초기화. 특정 조건이 충족될 경우 이 함수는 LoadLibraryEx를 호출한다.
- 레지스트리 함수들. 이 함수들은 advapi32.dll에 구현되어 있다. advapi32.dll이 초기화 되지 않았다면 크래시가 발생할 수 있다.
- CreateProcess 호출. 프로세스 생성은 다른 DLL을 로드할 수 있다.
- ExitThread 호출. DLL 디태치(detach) 과정 중에 스레드를 종료하면 로더 락을 다시 획득하도록 만들 수 있다. 이는 데드락이나 크래시가 유발된다.
- CreateThread 호출. 동기화만 하지 않는다면 스레드 생성은 괜찮을 수 있다. 하지만 위험하다.
- 네임드 파이프나 네임드 오브젝트 생성 (2000만 해당한다). 윈도우 2000에서 네임드 오브젝트 생성은 터미널 서비스 DLL에서 구현되어 있다. 해당 DLL이 초기화되어 있지 않다면 크래시.
- CRT에 포함된 메모리 관리 함수들. CRT DLL이 초기화되어 있지 않다면 크래시.
- user32.dll이나 gdi32.dll에 포함된 함수 호출. 일부 함수들은 다른 DLL을 로드하고, 이 사실은 크래시가 발생할 수 있다는 것을 의미한다.
- 관리된 코드 사용.
* 가장 아름다운 DllMain은 존재하지 않는 것이다 (비어 있는 함수 바디).
** 그래도 먼가 하고 싶다면 kernel32.dll에 포함된 함수 중에 위에서 언급되지 않은 것들만 쓰도록 한다. kernel32.dll이 초기화는 운영체제가 보장해 준다.
*** 글로벌 오브젝트에 대한 초기화 코드 또한 DllMain 과정에 포함된다. 따라서 글로벌 오브젝트의 생성자 내지는 초기화 함수 부분에 위에서 언급한 내용이 있어서는 안된다.
**** 초기화를 하지 말란 소린가? 아니다. 지연시키라는 말이다.
'저장소 > VC++' 카테고리의 다른 글
4K, 64K, 1MB, 1GB, 2GB의 DWORD 표현 (0) | 2013.02.20 |
---|---|
GetQueuedCompletionStatus의 0 transferred bytes (5) (0) | 2013.01.30 |
GetQueuedCompletionStatus의 0 transferred bytes (4) (0) | 2012.11.16 |
GetQueuedCompletionStatus의 0 transferred bytes (3) (0) | 2012.11.16 |
GetQueuedCompletionStatus의 0 transferred bytes (2) (0) | 2012.11.16 |