티스토리 뷰
MFC DLL에서 class에 vector를 담아서 Export 하려 시도 하였다.
처음에는 잘 되는 듯이 보였지만, class를 delete 하는 순간, 와장창 무너지기 시작했다.
계속해서 dbgheap.c의 _CrtIsValidHeapPointer(const void * pUserData) 안에 있는
HeapValidate( _crtheap, 0, pHdr(pUserData) ); 에서 FALSE을 리턴하여 ASSERT에 걸리게 되었다.
계속 디버깅을 해보니, vector의 소멸을 제대로 하지 못하고 있었다.
vector의 소멸자를 따라가 보니 dbgheap.c의 _crtheap이 caller의 heap을 가리키고 있는 것이 보였다.
아니, 애당초 call stack의 소멸 지점이 callee 인 dll이 아니라, caller인 application 이었다.
구글링을 해보니 STL 객체가 포함된 클래스를 내보내는 방법에 대한 msdn 문서가 있었다.
https://support.microsoft.com/ko-kr/kb/168958
중요한 것은, export 하는 class에서 사용하는 stl 타입의 선언을 아래와 같이 class 외부에서 한번 더 해줘야 하며,
template class __declspec(dllexport) std::vector<자료형>;
import 하는 class에서는 아래와 같이 선언해 줘야 한다는 것이다.
extern template class __declspec(import) std::vector<자료형>;
또한 STL 컨테이너 중에서 유일하게 vector<T> 타입만이 DLL Export가 가능하다.
위와 같이 해주니, vector의 소멸 시점에 정상적으로 callee인 DLL의 heap을 잡는 것이 보였고,
소멸 역시 제대로 이루어 졌다.
사족 )
이번 삽질을 통해 알아낸 재밌는 사실 중 하나는, MFC project의 경우 allocator delete(*)를 crt library에서 부르는 것이 아니라 mfc library에서 먼저 호출한다는 것이다.
이는 afxmem.cpp에 있는 void __cdecl operator delete(void* p)로 오게 된다. (결국엔 crt로 오기는 한다. [debug 모드에서 찍어보면 dbgheap.c로 간다])
crt library의 경우 중간 단계 없이 바로 delete로 간다.
이 순서는 재밌게도, 라이브러리 import 순서에 따르며 이렇게 되는 이유는, CRT 라이브러리가 new, delete 및 DllMain 함수에 대해서 약한 외부 링크를 사용하기 때문이다.
따라서 CRT 라이브러리가 링크 되기 전에 MFC 라이브러리를 링크 하면 MFC 라이브러리에 있는 new, delete 및 DllMain 함수가 먼저 호출되는 것이다.
C++도 아니고 C에서 이런 신박한 코드를 작성하다니 재밌다 :)
사족 참조 : https://support.microsoft.com/ko-kr/kb/148652
처음에는 잘 되는 듯이 보였지만, class를 delete 하는 순간, 와장창 무너지기 시작했다.
계속해서 dbgheap.c의 _CrtIsValidHeapPointer(const void * pUserData) 안에 있는
HeapValidate( _crtheap, 0, pHdr(pUserData) ); 에서 FALSE을 리턴하여 ASSERT에 걸리게 되었다.
계속 디버깅을 해보니, vector의 소멸을 제대로 하지 못하고 있었다.
vector의 소멸자를 따라가 보니 dbgheap.c의 _crtheap이 caller의 heap을 가리키고 있는 것이 보였다.
아니, 애당초 call stack의 소멸 지점이 callee 인 dll이 아니라, caller인 application 이었다.
구글링을 해보니 STL 객체가 포함된 클래스를 내보내는 방법에 대한 msdn 문서가 있었다.
https://support.microsoft.com/ko-kr/kb/168958
중요한 것은, export 하는 class에서 사용하는 stl 타입의 선언을 아래와 같이 class 외부에서 한번 더 해줘야 하며,
template class __declspec(dllexport) std::vector<자료형>;
import 하는 class에서는 아래와 같이 선언해 줘야 한다는 것이다.
extern template class __declspec(import) std::vector<자료형>;
또한 STL 컨테이너 중에서 유일하게 vector<T> 타입만이 DLL Export가 가능하다.
위와 같이 해주니, vector의 소멸 시점에 정상적으로 callee인 DLL의 heap을 잡는 것이 보였고,
소멸 역시 제대로 이루어 졌다.
사족 )
이번 삽질을 통해 알아낸 재밌는 사실 중 하나는, MFC project의 경우 allocator delete(*)를 crt library에서 부르는 것이 아니라 mfc library에서 먼저 호출한다는 것이다.
이는 afxmem.cpp에 있는 void __cdecl operator delete(void* p)로 오게 된다. (결국엔 crt로 오기는 한다. [debug 모드에서 찍어보면 dbgheap.c로 간다])
crt library의 경우 중간 단계 없이 바로 delete로 간다.
이 순서는 재밌게도, 라이브러리 import 순서에 따르며 이렇게 되는 이유는, CRT 라이브러리가 new, delete 및 DllMain 함수에 대해서 약한 외부 링크를 사용하기 때문이다.
따라서 CRT 라이브러리가 링크 되기 전에 MFC 라이브러리를 링크 하면 MFC 라이브러리에 있는 new, delete 및 DllMain 함수가 먼저 호출되는 것이다.
C++도 아니고 C에서 이런 신박한 코드를 작성하다니 재밌다 :)
사족 참조 : https://support.microsoft.com/ko-kr/kb/148652
'Development > Windows' 카테고리의 다른 글
| [WPF] User Control에 Custom Attribute로 값 전달하기 (0) | 2018.04.22 | 
|---|---|
| [WPF] cs 파일에 있는 변수를 xaml에서 binding 하기 (2) | 2018.04.22 | 
| 윈도우 배치 파일 강좌 (1) | 2018.01.06 | 
| [MFC] CRect의 IsRectNull()과 IsRectEmpty() (0) | 2016.02.16 | 
| [MFC] ToolBar 항목 지우는 방법 (2) | 2012.02.26 | 
| [TroubleShooting/MFC] Double Buffering을 구현하였는데도 깜빡이는 문제 (0) | 2012.02.24 | 
| [MFC] 다이얼로그 배경 투명하게 만들기 (0) | 2012.02.23 | 
| [MFC] Double Buffering 더블 버퍼링 사용하기 (0) | 2012.02.19 | 
					댓글
						
					
					
					
				
			
										공지사항
										
								
							
								
								
									최근에 올라온 글
									
							
								
								
									최근에 달린 댓글
									
							
								
								- Total
 
- Today
 
- Yesterday
 
									TAG
									
							
								
								- Quiz
 - API
 - Cloud
 - jni강좌
 - 리눅스
 - NDK
 - 음악
 - Visual C++
 - driver
 - winapi
 - AWS
 - 드라이버
 - source
 - jni
 - kering
 - android
 - gcc
 - linux
 - database
 - C
 - 프로그래밍
 - Python
 - 안드로이드
 - MFC
 - java
 - it
 - Troubleshooting
 - algorithm
 - db
 - C++
 
| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | 
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | 
| 30 | 
									글 보관함